Skip to content

(MOT-3944) feat(harness,queue): provision harness turn queue - #464

Merged
ytallo merged 7 commits into
mainfrom
feat/boot-provisioned-harness-queues
Jul 13, 2026
Merged

(MOT-3944) feat(harness,queue): provision harness turn queue#464
ytallo merged 7 commits into
mainfrom
feat/boot-provisioned-harness-queues

Conversation

@ytallo

@ytallo ytallo commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Fixes MOT-3944

Summary

  • Adds durable named function queues to the standalone queue worker, including persisted definitions, retries, FIFO grouping, and DLQ handling.
  • Defines harness-turn during harness startup before readiness.
  • Routes all harness turn-loop work to that FIFO queue, grouped by session_id.
  • Propagates trace context through queued delivery and removes legacy iii-queue dependencies and configuration entries.

Behavior

  • Harness startup fails if its queue cannot be ensured.
  • Restored jobs wait for harness::turn to register before delivery.
  • The queue uses concurrency 10, three retries, FIFO ordering per session, and the queue worker's default 30-minute invocation timeout.

Validation

  • cd queue && cargo test --lib — 122 passed.
  • cd harness && cargo test — 200 passed across library, manifest, and schema suites.
  • cargo fmt --check for both crates.
  • Live codex/gpt-5.4 harness turn completed through harness-turn.
  • Trace tree verified harness::send -> enqueue -> engine::queue::enqueue -> function_queue_job -> harness::turn.

Companion engine PR: iii-hq/iii#1950

Summary by CodeRabbit

  • New Features
    • Added durable named function queues with FIFO grouped ordering, concurrency limits, priorities, retry/backoff, and dead-letter handling.
    • Added queue definition + enqueue capabilities (queue::define / engine::queue::enqueue).
    • Harness now provisions and uses a dedicated harness-turn queue with ensured startup for per-session ordering.
  • Bug Fixes
    • Improved ack/nack, requeue, consumer stop/start behavior, and restart recovery to prevent lost/duplicated in-flight jobs.
  • Documentation
    • Updated setup/operational guides and worker configuration examples to remove the old queue worker and reflect the new queue worker behavior.

@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
workers Ready Ready Preview, Comment Jul 13, 2026 4:58pm
workers-tech-spec Ready Ready Preview, Comment Jul 13, 2026 4:58pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ff3a059-5ccf-4e6e-9f73-8c0b40227c79

📥 Commits

Reviewing files that changed from the base of the PR and between 3cc60a2 and 63b2bd0.

⛔ Files ignored due to path filters (1)
  • queue/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (34)
  • database/tests/e2e/config.yaml
  • harness/Makefile
  • harness/README.md
  • harness/engine.config.yaml
  • harness/iii.worker.yaml
  • harness/queue.config.yaml
  • harness/src/functions/mod.rs
  • harness/src/functions/turn.rs
  • harness/src/lib.rs
  • harness/src/locks.rs
  • harness/src/main.rs
  • harness/src/queue.rs
  • harness/src/turn_loop.rs
  • harness/tests/manifest.rs
  • queue/Cargo.toml
  • queue/README.md
  • queue/iii.worker.yaml
  • queue/src/adapter.rs
  • queue/src/adapters/builtin.rs
  • queue/src/adapters/memory.rs
  • queue/src/adapters/rabbitmq/adapter.rs
  • queue/src/adapters/rabbitmq/topology.rs
  • queue/src/adapters/redis.rs
  • queue/src/boot.rs
  • queue/src/config.rs
  • queue/src/configuration.rs
  • queue/src/functions.rs
  • queue/src/lib.rs
  • queue/src/main.rs
  • queue/src/manifest.rs
  • queue/src/observability.rs
  • queue/src/runtime.rs
  • queue/src/store.rs
  • queue/src/trigger.rs
💤 Files with no reviewable changes (1)
  • harness/engine.config.yaml
🚧 Files skipped from review as they are similar to previous changes (29)
  • harness/queue.config.yaml
  • harness/tests/manifest.rs
  • queue/iii.worker.yaml
  • harness/src/lib.rs
  • queue/src/lib.rs
  • queue/Cargo.toml
  • harness/src/functions/turn.rs
  • queue/src/manifest.rs
  • database/tests/e2e/config.yaml
  • queue/src/adapters/memory.rs
  • harness/src/queue.rs
  • queue/src/observability.rs
  • queue/src/adapters/redis.rs
  • harness/README.md
  • queue/src/main.rs
  • queue/src/adapters/rabbitmq/topology.rs
  • queue/src/config.rs
  • harness/src/locks.rs
  • harness/src/main.rs
  • queue/src/trigger.rs
  • queue/src/functions.rs
  • queue/src/boot.rs
  • queue/src/runtime.rs
  • queue/src/adapter.rs
  • harness/src/turn_loop.rs
  • queue/src/configuration.rs
  • queue/src/store.rs
  • queue/src/adapters/builtin.rs
  • queue/src/adapters/rabbitmq/adapter.rs

📝 Walkthrough

Walkthrough

The queue worker adds durable named function queues with persistent configuration, FIFO and concurrent processing, adapter recovery, runtime queue providers, tracing, and harness startup integration through the dedicated harness-turn queue.

Changes

Durable function queue platform

Layer / File(s) Summary
Queue contracts and durable storage
queue/src/adapter.rs, queue/src/config.rs, queue/src/store.rs
Adds validated function-queue configuration, adapter lifecycle contracts, persistent in-flight jobs, revision tracking, and requeue recovery.
Adapter delivery lifecycle
queue/src/adapters/*, queue/tests/*
Adds publishing, bounded consumption, acknowledgement, retry/DLQ handling, shutdown recovery, and adapter-specific function-queue behavior.
Runtime orchestration and worker boot
queue/src/runtime.rs, queue/src/boot.rs, queue/src/functions.rs, queue/src/configuration.rs, queue/src/trigger.rs, queue/src/main.rs
Adds queue definition and enqueue providers, FIFO processing, configuration refresh, provider registration, function availability checks, tracing, and boot reconciliation.
Harness turn queue provisioning
harness/src/*, harness/Makefile, harness/*.yaml, harness/tests/*
Ensures a harness-turn FIFO queue grouped by session_id, integrates readiness into startup, and updates harness queue wiring and worker configuration.
Packaging and documentation
queue/Cargo.toml, queue/README.md, queue/iii.worker.yaml, tech-specs/..., telegram-bot/iii.worker.yaml, {database,shell,storage}/tests/e2e/*.yaml
Updates package metadata, manifests, dependency declarations, queue documentation, and test configurations for standalone queue ownership.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Harness
  participant QueueWorker
  participant QueueAdapter
  participant Function
  Harness->>QueueWorker: queue::define harness-turn
  QueueWorker->>QueueAdapter: create FIFO consumer
  Harness->>QueueWorker: engine::queue::enqueue
  QueueWorker->>QueueAdapter: publish durable message
  QueueAdapter->>Function: deliver grouped turn
  Function-->>QueueAdapter: acknowledge or retry
Loading

Possibly related PRs

Suggested reviewers: andersonleal, sergiofilhowz

Poem

🐰 Queues bloom in burrows bright,
Turns hop softly through the night.
FIFO keeps each session neat,
Retries guide each carrot treat.
Harness-turn hums, ready to run.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.74% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: provisioning the harness turn queue across harness and queue.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/boot-provisioned-harness-queues

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

skill-check — worker

0 verified, 42 skipped (no docs/).

Layer Result
structure
vale
ai
render

Four for four. Nicely done.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
queue/src/store.rs (1)

242-256: 🚀 Performance & Scalability | 🔵 Trivial

enqueue performs blocking file I/O while holding the store mutex.

persist_if_needed runs synchronous std::fs::write/std::fs::rename while data = shared.inner.lock().await is still held. Every concurrent store operation (including consumer dequeue) blocks behind that disk write, and the blocking call also stalls the tokio worker thread. This is the cost of the rollback-on-failure guarantee (which does require holding the lock), but under enqueue load it can meaningfully serialize the queue.

Consider persisting via tokio::task::spawn_blocking (or an async fs) while still under the guard, or acknowledge this is acceptable given expected throughput. Note the other persist paths (dequeue/ack/nack) release the lock before persisting, so enqueue is uniquely affected.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@queue/src/store.rs` around lines 242 - 256, Refactor enqueue so
persist_if_needed does not execute synchronous file I/O while holding
shared.inner’s mutex. Preserve rollback semantics by snapshotting the previous
and updated state, release the guard before persistence, then reacquire it to
restore the previous state if persistence fails; alternatively move persistence
into spawn_blocking while clearly avoiding Tokio worker-thread blocking. Update
enqueue and related persistence handling consistently with dequeue, ack, and
nack.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@queue/src/runtime.rs`:
- Around line 424-439: Ensure the prepared adapter is shut down on every
pre-swap failure in the replacement flow. In the replacement block using
`setup_consumers`, explicitly clean up `new_adapter` when setup fails or when
`stop_all_consumers` fails, before propagating the original error; preserve the
existing consumer restart and error-reporting behavior.

---

Nitpick comments:
In `@queue/src/store.rs`:
- Around line 242-256: Refactor enqueue so persist_if_needed does not execute
synchronous file I/O while holding shared.inner’s mutex. Preserve rollback
semantics by snapshotting the previous and updated state, release the guard
before persistence, then reacquire it to restore the previous state if
persistence fails; alternatively move persistence into spawn_blocking while
clearly avoiding Tokio worker-thread blocking. Update enqueue and related
persistence handling consistently with dequeue, ack, and nack.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1b530321-8080-47d1-ac01-fb3d0d36152c

📥 Commits

Reviewing files that changed from the base of the PR and between f0b5259 and b419235.

⛔ Files ignored due to path filters (1)
  • queue/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (42)
  • database/tests/e2e/config.yaml
  • harness/Makefile
  • harness/README.md
  • harness/engine.config.yaml
  • harness/iii.worker.yaml
  • harness/queue.config.yaml
  • harness/src/functions/mod.rs
  • harness/src/functions/turn.rs
  • harness/src/lib.rs
  • harness/src/locks.rs
  • harness/src/main.rs
  • harness/src/queue.rs
  • harness/src/turn_loop.rs
  • harness/tests/manifest.rs
  • queue/Cargo.toml
  • queue/README.md
  • queue/iii.worker.yaml
  • queue/src/adapter.rs
  • queue/src/adapters/builtin.rs
  • queue/src/adapters/memory.rs
  • queue/src/adapters/rabbitmq/adapter.rs
  • queue/src/adapters/rabbitmq/topology.rs
  • queue/src/adapters/redis.rs
  • queue/src/boot.rs
  • queue/src/config.rs
  • queue/src/configuration.rs
  • queue/src/functions.rs
  • queue/src/lib.rs
  • queue/src/main.rs
  • queue/src/manifest.rs
  • queue/src/observability.rs
  • queue/src/runtime.rs
  • queue/src/store.rs
  • queue/src/trigger.rs
  • queue/tests/e2e_durability.rs
  • queue/tests/e2e_rabbitmq.rs
  • shell/tests/e2e/config-jailed.yaml
  • shell/tests/e2e/config.yaml
  • storage/tests/e2e/config.all.yaml
  • storage/tests/e2e/config.yaml
  • tech-specs/2026-06-agentic/harness.md
  • telegram-bot/iii.worker.yaml
💤 Files with no reviewable changes (5)
  • harness/engine.config.yaml
  • storage/tests/e2e/config.yaml
  • shell/tests/e2e/config-jailed.yaml
  • shell/tests/e2e/config.yaml
  • storage/tests/e2e/config.all.yaml

Comment thread queue/src/runtime.rs
Comment on lines +424 to +439
if let Some((new_adapter, name)) = replacement {
let old_adapter = self.adapter.current().await;
self.setup_consumers(new_adapter.clone(), &next.queue_configs)
.await?;
if let Err(error) = self.stop_all_consumers(old_adapter.clone()).await {
let restart = self
.setup_and_start_consumers(old_adapter, &old.queue_configs)
.await;
let restart_summary = result_summary(&restart);
if let Ok(consumers) = restart {
self.replace_all_consumers(consumers).await?;
}
anyhow::bail!(
"cannot stop previous queue consumers before adapter replacement: {error}; consumer restart: {restart_summary}"
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Close the prepared adapter on pre-swap failures.

If setup succeeds but stopping old consumers fails, new_adapter is returned without shutdown(). The direct ? on Line 426 has the same leak path. Repeated failed reconfigurations can accumulate adapter connections/resources.

Proposed cleanup
-            self.setup_consumers(new_adapter.clone(), &next.queue_configs)
-                .await?;
+            if let Err(error) = self.setup_consumers(new_adapter.clone(), &next.queue_configs).await {
+                new_adapter.shutdown().await;
+                return Err(error);
+            }
             if let Err(error) = self.stop_all_consumers(old_adapter.clone()).await {
+                new_adapter.shutdown().await;
                 let restart = self
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if let Some((new_adapter, name)) = replacement {
let old_adapter = self.adapter.current().await;
self.setup_consumers(new_adapter.clone(), &next.queue_configs)
.await?;
if let Err(error) = self.stop_all_consumers(old_adapter.clone()).await {
let restart = self
.setup_and_start_consumers(old_adapter, &old.queue_configs)
.await;
let restart_summary = result_summary(&restart);
if let Ok(consumers) = restart {
self.replace_all_consumers(consumers).await?;
}
anyhow::bail!(
"cannot stop previous queue consumers before adapter replacement: {error}; consumer restart: {restart_summary}"
);
}
if let Some((new_adapter, name)) = replacement {
let old_adapter = self.adapter.current().await;
if let Err(error) = self
.setup_consumers(new_adapter.clone(), &next.queue_configs)
.await
{
new_adapter.shutdown().await;
return Err(error);
}
if let Err(error) = self.stop_all_consumers(old_adapter.clone()).await {
new_adapter.shutdown().await;
let restart = self
.setup_and_start_consumers(old_adapter, &old.queue_configs)
.await;
let restart_summary = result_summary(&restart);
if let Ok(consumers) = restart {
self.replace_all_consumers(consumers).await?;
}
anyhow::bail!(
"cannot stop previous queue consumers before adapter replacement: {error}; consumer restart: {restart_summary}"
);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@queue/src/runtime.rs` around lines 424 - 439, Ensure the prepared adapter is
shut down on every pre-swap failure in the replacement flow. In the replacement
block using `setup_consumers`, explicitly clean up `new_adapter` when setup
fails or when `stop_all_consumers` fails, before propagating the original error;
preserve the existing consumer restart and error-reporting behavior.

@guibeira guibeira left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we update only the harness and queue? i would like to first update those, and them we can run some tests. If everything works fine we can come back and update them.

Comment thread queue/src/observability.rs Outdated
use tracing_opentelemetry::OpenTelemetryLayer;
use tracing_subscriber::registry::LookupSpan;

const TRACER_NAME: &str = "iii-queue";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

let's switch to just queue

@ytallo
ytallo force-pushed the feat/boot-provisioned-harness-queues branch from 3cc60a2 to 63b2bd0 Compare July 13, 2026 16:57
@ytallo
ytallo merged commit e7a0986 into main Jul 13, 2026
55 checks passed
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.

2 participants