Run Duo note messaging callbacks in a high-urgency worker
What does this MR do and why?
Splits messaging-callback dispatch so the DB-only @GitLabDuo note path runs at :high urgency, without paying the resource cost of scheduling a worker that only no-ops.
Ai::Messaging::CallbackWorker served both the Slack adapter (which calls the Slack API) and the gitlab_duo_note adapter (DB-only). Because it declared worker_has_external_dependencies!, it could not also be urgency :high — RuboCop forbids the combination. That kept the @GitLabDuo MR-reply path at :low urgency, adding noticeable scheduling delay before Duo posts a reply.
This MR introduces a single high-urgency dispatcher that resolves the adapter once and either delivers inline or forwards:
- Adds an
Adapters::Base.has_external_dependencies?capability flag (defaultfalse);Slackoverrides it totrue. - Extracts the shared dispatch logic into an
Ai::Messaging::CallbackDispatchconcern with aforward_eventhook (default: terminal, never forwards). - New
Ai::Messaging::CallbackDispatchWorker(urgency :high, no external deps) is the sole EventStore subscriber. It resolves the workflow's adapter once (cheap, DB-only); DB-only adapters are delivered inline (the latency-sensitive path), external-dependency adapters are forwarded toCallbackWorkerviaperform_async. CallbackWorkerbecomes terminal external/Slack delivery (keepsworker_has_external_dependencies!) and handles inline whatever adapter it is handed.
This mirrors an existing in-domain pattern — CreateCheckpointService#enqueue_messaging_progress_delivery checks a capability on the adapter class (supports_live_progress?) and does a targeted enqueue. New adapters route automatically by their has_external_dependencies? value.
Feature flag: the dispatch is gated behind gitlab_duo_note_callback_high_urgency (gitlab_com_derisk, default off), per Sidekiq compatibility across updates — a new worker must not be scheduled before the Sidekiq fleet has the class. The if: is evaluated per publish, so it is runtime-toggleable:
- flag off → the pre-existing
CallbackWorkersubscribes and handles everything inline (today's behavior). Safe fallback — the forward target already exists in production. - flag on →
CallbackDispatchWorkersubscribes (sole) and forwards Slack toCallbackWorker.
Note: the DB-only path runs Notes::CreateService, which must stay within the high-urgency SLO (median <1s, p99 <10s). Ping @gitlab-com/gl-infra/data-access/durability if the expected shard-load increase exceeds 5%. Slack gets one extra scheduling hop (dispatch → forward → deliver), which is acceptable since it is external-dependency / not latency-critical.
Screenshots or screen recordings
N/A — backend-only change.
| File | Before | After |
|---|---|---|
ee/app/workers/ai/messaging/callback_worker.rb |
sole subscriber, dispatches all adapters, :low urgency, external deps |
terminal external/Slack delivery + forward target; handles inline whatever it is handed |
ee/app/workers/ai/messaging/callback_dispatch_worker.rb |
(did not exist) | sole subscriber, urgency :high, no external deps; inline DB-only, forward external |
ee/app/workers/concerns/ai/messaging/callback_dispatch.rb |
(did not exist) | shared dispatch + forward_event hook |
How to set up and validate locally
- Enable the flag:
Feature.enable(:gitlab_duo_note_callback_high_urgency)in a Rails console. - Mention
@GitLabDuoin an MR comment on a project with Duo Code Review enabled; confirm the reply posts and arrives faster (delivered inline byCallbackDispatchWorkerat:highurgency). - Disable the flag and repeat; confirm the reply still posts (served by the legacy
CallbackWorkersubscriber). - From Slack, mention Duo and confirm Slack replies/reactions still work (forwarded to
CallbackWorkerwhen the flag is on; handled directly when off).
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
References
- Issue: #605336 (closed)
- Prior discussion: !238375 (comment 3395712045)
- Feature flag rollout: #605184