-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
fix(reprocessing): Cull parallel reprocessing tasks #123693
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,5 @@ | ||||||||||||
| import uuid | ||||||||||||
| from collections.abc import Mapping | ||||||||||||
| from datetime import datetime | ||||||||||||
| from typing import Any | ||||||||||||
|
|
||||||||||||
|
|
@@ -28,6 +29,12 @@ def _get_remaining_key(project_id: int, group_id: int) -> str: | |||||||||||
| return f"re2:remaining:{{{project_id}:{group_id}}}" | ||||||||||||
|
|
||||||||||||
|
|
||||||||||||
| def _get_page_claim_key( | ||||||||||||
| project_id: int, group_id: int, new_group_id: int, timestamp: str, event_id: str | ||||||||||||
| ) -> str: | ||||||||||||
| return f"re2:pageclaim:{{{project_id}:{group_id}}}:{new_group_id}:{timestamp}:{event_id}" | ||||||||||||
|
|
||||||||||||
|
|
||||||||||||
| class RedisReprocessingStore(ReprocessingStore): | ||||||||||||
| def __init__(self, **options: dict[str, Any]) -> None: | ||||||||||||
| cluster = options.pop("cluster", "default") | ||||||||||||
|
|
@@ -180,3 +187,18 @@ def get_progress(self, group_id: int) -> ReprocessingInfo | None: | |||||||||||
| if info is None: | ||||||||||||
| return None | ||||||||||||
| return orjson.loads(info) | ||||||||||||
|
|
||||||||||||
| def try_claim_page( | ||||||||||||
| self, | ||||||||||||
| project_id: int, | ||||||||||||
| group_id: int, | ||||||||||||
| new_group_id: int, | ||||||||||||
| state: Mapping[str, str] | None, | ||||||||||||
| claimant: str, | ||||||||||||
| ) -> bool: | ||||||||||||
| timestamp = state["timestamp"] if state is not None else "start" | ||||||||||||
| event_id = state["event_id"] if state is not None else "start" | ||||||||||||
| key = _get_page_claim_key(project_id, group_id, new_group_id, timestamp, event_id) | ||||||||||||
| if self.redis.set(key, claimant, nx=True, ex=settings.SENTRY_REPROCESSING_PAGE_CLAIM_TTL): | ||||||||||||
| return True | ||||||||||||
| return self.redis.get(key) == claimant | ||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Page claim TTL prevents eventual cullingMedium Severity
Additional Locations (1)Reviewed by Cursor Bugbot for commit 696e866. Configure here.
Comment on lines
+202
to
+204
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
(Assuming our Redis version is current enough (>6.2) to support this.) |
||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,7 @@ | |
| from sentry.search.eap.occurrences.query_utils import build_group_id_in_filter | ||
| from sentry.services import eventstore | ||
| from sentry.services.eventstore.models import Event | ||
| from sentry.services.eventstore.reprocessing import reprocessing_store | ||
| from sentry.silo.base import SiloMode | ||
| from sentry.tasks.base import instrumented_task | ||
| from sentry.tasks.process_buffer import buffer_incr | ||
|
|
@@ -109,6 +110,33 @@ def reprocess_group( | |
|
|
||
| assert new_group_id is not None | ||
|
|
||
| # To the best of our knowledge we still have quite some `reprocess_group` tasks running in parallel, this logic | ||
| # is intended to cull all but one. This is temporary to recover from a bad state and should be dead code after that. | ||
|
Comment on lines
+113
to
+114
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment should probably refer to the INC in question by name, otherwise this is going to be confusing in the future. |
||
| if activation_id: | ||
| try: | ||
| page_owned = reprocessing_store.try_claim_page( | ||
| project_id=project_id, | ||
| group_id=group_id, | ||
| new_group_id=new_group_id, | ||
| state=query_state, | ||
| claimant=activation_id, | ||
| ) | ||
| except Exception: | ||
| logger.warning("reprocessing2.page_claim.error", exc_info=True) | ||
| page_owned = True | ||
| if not page_owned: | ||
| logger.info( | ||
| "reprocessing2.page_claim.culled", | ||
| extra={ | ||
| "project_id": project_id, | ||
| "group_id": group_id, | ||
| "new_group_id": new_group_id, | ||
| "query_state": query_state, | ||
| "activation_id": activation_id, | ||
| }, | ||
| ) | ||
| return | ||
|
|
||
| query_state, events = task_run_batch_query( | ||
| filter=eventstore.Filter(project_ids=[project_id], group_ids=[group_id]), | ||
| batch_size=settings.SENTRY_REPROCESSING_PAGE_SIZE, | ||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are the nested braces around
project_id/group_idfor?