Skip to content

Add headers and hooks to taskbroker client#587

Merged
gricha merged 7 commits intomainfrom
tasbroker-client-headers
Apr 8, 2026
Merged

Add headers and hooks to taskbroker client#587
gricha merged 7 commits intomainfrom
tasbroker-client-headers

Conversation

@gricha
Copy link
Copy Markdown
Member

@gricha gricha commented Apr 3, 2026

Relevant context: https://www.notion.so/sentry/RFC-Unified-ViewerContext-via-ContextVar-32f8b10e4b5d81988625cb5787035e02

I think if we want to implicitly pass VC across the wire, we'll need to do these.

to make this work fully implicitly i add hooks to both pack it into context as header on producer side and unpack it on the consumer side automatically.

@gricha gricha requested a review from markstory April 3, 2026 18:29
@gricha gricha requested a review from a team as a code owner April 3, 2026 18:29
gricha and others added 3 commits April 3, 2026 11:36
ExternalNamespace was missing context_hooks, so on_dispatch hooks
would not fire for tasks dispatched to external applications.

Also fixes black formatting issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
create_activation passes headers as MutableMapping[str, Any], not
dict[str, str]. Values are stringified after hooks run.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests verify:
- on_dispatch injects headers during create_activation
- No headers injected when no hooks registered
- Multiple hooks all get called
- on_execute receives activation headers during child_process execution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

gricha added a commit to getsentry/sentry that referenced this pull request Apr 3, 2026
Implement ViewerContextHook that propagates ViewerContext through
TaskBroker task headers. On dispatch, the hook reads from the
contextvar and injects org_id, user_id, and actor_type into task
headers. On execution, it restores the ViewerContext from headers
into a viewer_context_scope.

This enables implicit identity propagation through async tasks
without requiring callsites to manually pass user context.

Depends on getsentry/taskbroker#587 for the ContextHook protocol.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gricha and others added 2 commits April 6, 2026 14:16
Add missing class variable annotation for StubContextHook.last_executed and
widen RecordingHook.on_dispatch parameter type to MutableMapping to
match the ContextHook protocol.

Co-Authored-By: Claude Opus 4.6 <noreply@example.com>
Run black on task.py and isort on test_worker.py to fix CI lint
failures.

Co-Authored-By: Claude Opus 4.6 <noreply@example.com>
@george-sentry
Copy link
Copy Markdown
Member

Everything seems okay here, aside from maybe the AI reviewer comments. The only impact I can see is that task activations may be larger, which could result in a small decrease in throughput. I will let someone else review and approve though 🙂

@gricha
Copy link
Copy Markdown
Member Author

gricha commented Apr 6, 2026

Thank you!

Copy link
Copy Markdown
Member

@evanh evanh left a comment

Choose a reason for hiding this comment

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

Can you clarify what these hooks will actually do?

It would also be nice to have an understanding of the performance of the hooks vs. the actual task_func, through metrics or sentry spans.

@gricha
Copy link
Copy Markdown
Member Author

gricha commented Apr 7, 2026

Yup of course. Here's a good example: getsentry/sentry#112217 (check ViewerContextHook)

The point of this is to be able to register an action that happens on both dispatch (producer side) and execute (consumer side). In this specific case this allows me to automatically and implicitly pass viewer context whenever a task is created, and then unpack it on the consumer side and pack it directly into contextvars.

For performance tests, anything specific you want me to do here? Do you have specific way of testing this, or metrics you are tracking we can look at in rollout?

@gricha gricha requested a review from evanh April 7, 2026 16:39
Comment on lines +371 to +372
for hook in context_hooks:
stack.enter_context(hook.on_execute(headers))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be helpful to have a timer around context rebuilding. Currently this latency would show up as task execution time, and a failure in rebuilding context counts as a task failure.

- Wrap context hook execution in metrics.timer to measure context
  rebuild latency separately from task execution time
- Use explicit None check for context_hooks to avoid empty list problem
  when hooks are bound after initialization
@gricha gricha requested a review from markstory April 7, 2026 21:13
@gricha gricha merged commit 10749ac into main Apr 8, 2026
23 checks passed
@gricha gricha deleted the tasbroker-client-headers branch April 8, 2026 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants