Skip to content

feat(ownership): Migrate assignee existence cache invalidation to use timestamp versioning on ownership#106479

Merged
shashjar merged 6 commits intomasterfrom
migrate-assignee-exists-cache-cache-invalidation-to-ownership-timestamp-versioning
Jan 26, 2026
Merged

feat(ownership): Migrate assignee existence cache invalidation to use timestamp versioning on ownership#106479
shashjar merged 6 commits intomasterfrom
migrate-assignee-exists-cache-cache-invalidation-to-ownership-timestamp-versioning

Conversation

@shashjar
Copy link
Member

@shashjar shashjar commented Jan 16, 2026

Follow-up to #106108.

Closes ID-1238.

This PR extends the O(1) timestamp-based cache invalidation pattern (introduced in the above PR for the issue owners debounce cache) to the assignee existence check cache.

The invalidate_assignee_exists_cache method previously performed expensive fan-out O(n) cache invalidation. When CODEOWNERS or ownership rules changed, we would previously:

  1. Query all groups in the project with recent events
  2. Delete the assignee existence cache entry for each group individually (via batched cache.delete_many)

Before:

  • Assignee existence cache stored a simple boolean
  • On ownership change: delete cache entries for ALL active groups in the project (O(n))

After:

  • Assignee existence cache stores (value, timestamp) tuple
  • On ownership change, set the project-wide ownership_changed_at timestamp
  • On cache read:
    • If cache is None --> query DB, cache result with timestamp
    • If cache is a tuple (value, timestamp), compare against ownership_changed_at
      • If ownership_changed_at is None or ownership_changed_at < cached_timestamp --> use cached value
      • If ownership_changed_at >= cached_timestamp --> ownership rules changed, re-query DB
    • If cache is old format (boolean) --> backwards compatibility, use value directly

Follow-Up

Left TODO in the code:

  • Remove backwards compatibility logic for old boolean cache values 24 hrs after this PR is rolled out

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Jan 16, 2026
@linear
Copy link

linear bot commented Jan 20, 2026

@shashjar shashjar requested a review from a team January 20, 2026 18:52
@shashjar shashjar marked this pull request as ready for review January 20, 2026 18:52
@shashjar
Copy link
Member Author

bugbot run

data=data,
)
record_group_history(group, GroupHistoryStatus.ASSIGNED, actor=acting_user)
GroupOwner.invalidate_assignee_exists_cache(group.id)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a cache invalidation here (in the assign method) to expire stale value

@shashjar shashjar merged commit 4844892 into master Jan 26, 2026
66 checks passed
@shashjar shashjar deleted the migrate-assignee-exists-cache-cache-invalidation-to-ownership-timestamp-versioning branch January 26, 2026 19:57
dashed pushed a commit that referenced this pull request Jan 26, 2026
… timestamp versioning on ownership (#106479)

Follow-up to #106108.

Closes
[ID-1238](https://linear.app/getsentry/issue/ID-1238/cache-for-assignee-existence-check-uses-expensive-fan-out-invalidation).

This PR extends the O(1) timestamp-based cache invalidation pattern
(introduced in the above PR for the issue owners debounce cache) to the
assignee existence check cache.

The `invalidate_assignee_exists_cache` method previously performed
expensive fan-out O(n) cache invalidation. When CODEOWNERS or ownership
rules changed, we would previously:
1. Query all groups in the project with recent events
2. Delete the assignee existence cache entry for each group individually
(via batched `cache.delete_many`)

**Before:**
- Assignee existence cache stored a simple boolean
- On ownership change: delete cache entries for ALL active groups in the
project (O(n))

**After:**
- Assignee existence cache stores `(value, timestamp)` tuple
- On ownership change, set the project-wide `ownership_changed_at`
timestamp
- On cache read:
    - If cache is `None` --> query DB, cache result with timestamp
- If cache is a tuple `(value, timestamp)`, compare against
`ownership_changed_at`
- If `ownership_changed_at` is `None` or `ownership_changed_at` <
`cached_timestamp` --> use cached value
- If `ownership_changed_at` >= `cached_timestamp` --> ownership rules
changed, re-query DB
- If cache is old format (boolean) --> backwards compatibility, use
value directly

### Follow-Up

Left TODO in the code:
- Remove backwards compatibility logic for old boolean cache values 24
hrs after this PR is rolled out
JonasBa pushed a commit that referenced this pull request Jan 27, 2026
… timestamp versioning on ownership (#106479)

Follow-up to #106108.

Closes
[ID-1238](https://linear.app/getsentry/issue/ID-1238/cache-for-assignee-existence-check-uses-expensive-fan-out-invalidation).

This PR extends the O(1) timestamp-based cache invalidation pattern
(introduced in the above PR for the issue owners debounce cache) to the
assignee existence check cache.

The `invalidate_assignee_exists_cache` method previously performed
expensive fan-out O(n) cache invalidation. When CODEOWNERS or ownership
rules changed, we would previously:
1. Query all groups in the project with recent events
2. Delete the assignee existence cache entry for each group individually
(via batched `cache.delete_many`)

**Before:**
- Assignee existence cache stored a simple boolean
- On ownership change: delete cache entries for ALL active groups in the
project (O(n))

**After:**
- Assignee existence cache stores `(value, timestamp)` tuple
- On ownership change, set the project-wide `ownership_changed_at`
timestamp
- On cache read:
    - If cache is `None` --> query DB, cache result with timestamp
- If cache is a tuple `(value, timestamp)`, compare against
`ownership_changed_at`
- If `ownership_changed_at` is `None` or `ownership_changed_at` <
`cached_timestamp` --> use cached value
- If `ownership_changed_at` >= `cached_timestamp` --> ownership rules
changed, re-query DB
- If cache is old format (boolean) --> backwards compatibility, use
value directly

### Follow-Up

Left TODO in the code:
- Remove backwards compatibility logic for old boolean cache values 24
hrs after this PR is rolled out
shashjar added a commit that referenced this pull request Jan 28, 2026
…stence cache (#107022)

Follow-up to #106479.

Closes
[ID-1238](https://linear.app/getsentry/issue/ID-1238/cache-for-assignee-existence-check-uses-expensive-fan-out-invalidation).

It's been >24 hours since the PR above was deployed and the assignee
existence cache values were migrated to the new format. We can therefore
remove the backwards compatibility logic, since all cache values will
now correctly be 2-tuples of `(assignee_exists,
assignee_debounce_time)`.
priscilawebdev pushed a commit that referenced this pull request Feb 2, 2026
… timestamp versioning on ownership (#106479)

Follow-up to #106108.

Closes
[ID-1238](https://linear.app/getsentry/issue/ID-1238/cache-for-assignee-existence-check-uses-expensive-fan-out-invalidation).

This PR extends the O(1) timestamp-based cache invalidation pattern
(introduced in the above PR for the issue owners debounce cache) to the
assignee existence check cache.

The `invalidate_assignee_exists_cache` method previously performed
expensive fan-out O(n) cache invalidation. When CODEOWNERS or ownership
rules changed, we would previously:
1. Query all groups in the project with recent events
2. Delete the assignee existence cache entry for each group individually
(via batched `cache.delete_many`)

**Before:**
- Assignee existence cache stored a simple boolean
- On ownership change: delete cache entries for ALL active groups in the
project (O(n))

**After:**
- Assignee existence cache stores `(value, timestamp)` tuple
- On ownership change, set the project-wide `ownership_changed_at`
timestamp
- On cache read:
    - If cache is `None` --> query DB, cache result with timestamp
- If cache is a tuple `(value, timestamp)`, compare against
`ownership_changed_at`
- If `ownership_changed_at` is `None` or `ownership_changed_at` <
`cached_timestamp` --> use cached value
- If `ownership_changed_at` >= `cached_timestamp` --> ownership rules
changed, re-query DB
- If cache is old format (boolean) --> backwards compatibility, use
value directly

### Follow-Up

Left TODO in the code:
- Remove backwards compatibility logic for old boolean cache values 24
hrs after this PR is rolled out
priscilawebdev pushed a commit that referenced this pull request Feb 2, 2026
…stence cache (#107022)

Follow-up to #106479.

Closes
[ID-1238](https://linear.app/getsentry/issue/ID-1238/cache-for-assignee-existence-check-uses-expensive-fan-out-invalidation).

It's been >24 hours since the PR above was deployed and the assignee
existence cache values were migrated to the new format. We can therefore
remove the backwards compatibility logic, since all cache values will
now correctly be 2-tuples of `(assignee_exists,
assignee_debounce_time)`.
@github-actions github-actions bot locked and limited conversation to collaborators Feb 11, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants