Skip to content

coordinator: multi-channel priority queue + stream affinity + multi-subscription consume - #2

Open
simonhachey wants to merge 5 commits into
mainfrom
simon/lrq-coordinator-queue
Open

simonhachey wants to merge 5 commits into
mainfrom
simon/lrq-coordinator-queue

Conversation

@simonhachey

@simonhachey simonhachey commented Jul 21, 2026

Copy link
Copy Markdown

Summary

Adds workload-isolation plumbing to the coordinator so long-running, IO-bound UDFs (e.g. LLM classification, on the order of seconds per call) can be processed on dedicated worker pools without head-of-line-blocking the fast path. Dormant and backwards-compatible by default — the existing Kafka default path and the single-PUBSUB_SUBSCRIPTION_ID pubsub path are unchanged (the recvrecv_for(ServedQueue::Fast) refactor is the same biased [sync, async] select as before).

What's in it

  • N-channel priority queue (priority_queue.rs): adds notif-steady and notif-batch channels alongside sync/async, a Channel enum, and a ServedQueue enum. A new affinity-aware recv_for(ServedQueue) lets a connection pull only from the channel(s) its pool serves; ServedQueue::Fast (the default) preserves the existing [sync, async] biased select exactly (sync first, async→sync fallback, unchanged queue-time metric).
  • Multi-subscription consume (main.rs, consumer/pubsub.rs): the coordinator can now consume several Pub/Sub subscriptions — one pull manager each, its own FlowControl budget — routing each subscription's actions into a specific channel. Configured via OSPREY_COORDINATOR_SUBSCRIPTIONS (a sub_id:channel list). Unset ⇒ falls back to the single PUBSUB_SUBSCRIPTION_IDasync channel (today's behavior).
  • Shutdown: the new channels are nacked on shutdown alongside sync/async.
  • New per-channel queue-size gauges.

Dormant by design

Nothing is activated in this PR: with OSPREY_COORDINATOR_SUBSCRIPTIONS unset the coordinator runs its single-subscription async path exactly as before, and no worker advertises a served_queue yet — so the new channels are never fed or drained. The dispatch-side affinity (workers advertising which channel they serve) and the dedicated worker pools land in follow-up PRs.

One intentional behavior change: a pubsub coordinator started with neither OSPREY_COORDINATOR_SUBSCRIPTIONS nor PUBSUB_SUBSCRIPTION_ID set now fails fast at startup instead of silently subscribing to a hardcoded default name. In practice both real configs are unaffected (Kafka default is untouched; the pubsub path requires PUBSUB_SUBSCRIPTION_ID), but it's a deliberate fail-on-misconfig, not byte-for-byte.

Testing

  • cargo test — 60/60 (new: channel/affinity recv_for, OSPREY_COORDINATOR_SUBSCRIPTIONS parsing incl. error paths, notif-channel shutdown nacks).
  • cargo check clean.

Follow-ups (separate PRs)

  • Proto ClientDetails.served_queue + affinity-aware dispatch + worker-side advertising.
  • Dedicated, backlog-autoscaled worker pools per channel and the subscriptions that feed them.

🤖 Generated with Claude Code

…ware recv_for

Purely additive priority-queue plumbing for long-running queues Task 1:
- Channel enum (Sync/Async/NotifSteady/NotifBatch) replaces Priority
- ServedQueue enum + from_str (unknown/"" -> Fast, legacy default)
- PriorityQueueSender::send(action, Channel), len(Channel), send_notif_steady/send_notif_batch
- PriorityQueueReceiver::recv_for(ServedQueue, metrics) with affinity-aware
  dispatch; recv() now delegates to recv_for(Fast, ..), preserving the
  existing biased sync>async behavior and async-queue-time metric recording

No subscription routing into the new channels yet (later task). Existing
send_sync/send_async/recv/len_sync/len_async callers are unaffected.
@simonhachey
simonhachey marked this pull request as ready for review July 22, 2026 01:11
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.

1 participant