Repository navigation
[WIP] feat(client): Add completion hooks and detect masked processing deadlines - #840
Closed
sentry-junior[bot] wants to merge 1 commit into
Closed
sentry-junior[bot] wants to merge 1 commit into
sentry-junior[bot] wants to merge 1 commit into
Conversation
…ines The processing deadline is raised as a BaseException from SIGALRM and can interrupt library cleanup at any point. In Django, a deadline that lands in Atomic.__exit__ leaves the connection in manual transaction management and the driver raises its own error, which hides the deadline. The child then runs every later task on the broken connection. Treat an exception whose chain contains the deadline as a deadline, and add an optional TaskCompletionHook that runs after every task once the alarm is disarmed so applications can reset process state the deadline broke. Co-Authored-By: Rudra Patel <rudra.patel@sentry.io>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Work in progress. This draft scopes a fix and is not ready for review.
The worker child enforces
processing_deadline_durationby raisingProcessingDeadlineExceeded(aBaseException) from a SIGALRM handler. That can interrupt library cleanup at any point. In Sentry it lands inside Django'sAtomic.__exit__afterin_atomic_blockis cleared but before COMMIT. psycopg2 then refusesset_autocommit(True)withset_session cannot be used inside a transaction, which replaces the deadline. The Django connection is left in manual transaction management with a transaction that never commits. The child keeps the connection and runs later tasks on it, so they fail withon_commit() cannot be used in manual transaction managementor "You can't execute queries until the end of the 'atomic' block", or they lose their writes, until the child reaches its max task count.Examples in Sentry:
What this PR does:
ProcessingDeadlineExceededanywhere in its__cause__/__context__chain, it goes through the deadline path: same report, sameprocessing_deadline_exceededmetric (with a newmaskedtag), and retry decided against the deadline. Today it falls intoexcept Exception, skips the deadline metric, and may retry silently.TaskCompletionHook(TaskbrokerApp(completion_hooks=[...])).after_task(activation, status, deadline_exceeded)runs after every task, success or failure, oncetimeout_alarmhas exited. A hook can repair what the deadline broke without the deadline interrupting the repair. Hook errors are logged and counted, and never stop the child.The client stays Django-agnostic. The Sentry side would register a hook that checks each initialized connection (Django
autocommit,in_atomic_block, driverautocommit, drivertransaction_status == IDLE) and closes and resets any unhealthy one. That check issues no SQL. It has to run after every task, not only whendeadline_exceededis set, because a deadline can also be swallowed outright:sentry_sdk'scapture_internal_exceptions()catchesBaseException.Open questions before this is ready:
handle_alarm's docstring already says it should. Recycling covers state a hook can't know about (client sessions, locks, contextvars), but on busy pools it would mean a process restart for every deadline. It could be a per-pool or per-task option.after_task(activation, status, deadline_exceeded)the right shape, or should hooks get a result object so fields can be added later without breaking them?handle_task_exceptionwas moved out of the loop body unchanged so the deadline handling could be shared. The diff is larger than the behavior change.via Rudra Patel.
--
View Session [Sentry]