Skip to content

Optimize#49

Merged
IGN-Styly merged 60 commits into
mainfrom
optimize
Jul 21, 2026
Merged

Optimize#49
IGN-Styly merged 60 commits into
mainfrom
optimize

Conversation

@IGN-Styly

@IGN-Styly IGN-Styly commented Jul 18, 2026

Copy link
Copy Markdown
Member

Goal: Establish a Core base for multiple transport methods like TCP, GRPC etc.

Summary by CodeRabbit

  • New Features
    • Added task lifecycle operations: submit, lease, renew, complete, cancel, query, and purge.
    • Implemented persistent task storage with automatic recovery and lease reaping via RocksDB.
    • Added batched (task-block) event hooks for acquisition, execution, creation, and publishing.
    • Enabled runtime module loading from .rf packages.
  • Bug Fixes
    • Improved handling of expired/abandoned task leases so work returns to the queue.
  • Breaking Changes
    • Updated task/event APIs to batched task-block variants; removed prior non-block event surface and older RPC/CLI components.
    • Updated configuration to use auth_token.
  • Documentation
    • Removed outdated RFC documents related to superseded APIs and event behavior.

IGN-Styly and others added 30 commits May 31, 2026 20:10
- Rename task acquire/create/publish events to block-level variants
- Update server auth checks to use immutable API borrows
- Change CreateTaskBlock/PublishTaskBlock to work on TaskBlock payloads
- Add LEASED task state and move queued/solved access to sled helpers
- Use direct DB helpers for queued/solved deletes, scans, and inserts
- Serialize queue refills per identifier to avoid TOCTOU duplicates
- Remove queued entries after publish and prune expired leases periodically
- Switch client/server/packer paths to block-oriented task acquire, publish, and delete calls
- Rename task lifecycle events to block variants and update API types
- Add an in-process gRPC TPS benchmark for enqueue/process throughput
@IGN-Styly
IGN-Styly marked this pull request as ready for review July 20, 2026 18:40
@greptile-apps

greptile-apps Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR establishes the task nucleus core — submit, lease, renew, complete, cancel, and query — backed by RocksDB persistence, and migrates the event surface to batch task-block variants. It resolves several previously-flagged issues: submit now returns the generated task ID, cancel correctly releases the lease (leaving the DB record intact), the error module is now public, complete properly guards all error paths with a clear_dedup closure, and the DB open panic includes a diagnostic message.

  • Nucleus lifecycle (enginelib/src/nucleus/*): All six operations are in place; cancel is a non-blocking try_send-based lease release; complete writes f: before deleting t: and always clears the dedup entry on both success and failure paths.
  • Query API (nucleus/query.rs): Adds Get, Scan (cursor-paginated, O(limit)), Delete, PurgePrefix (range tombstone), EstimateKeys, and EstimateSize — all designed to avoid full-keyspace scans.
  • Batch events: Single-task before_task_* / task_acquired events replaced with task-block variants; RFC docs for superseded designs removed.

Confidence Score: 5/5

The core task lifecycle is now substantially correct and safe to merge.

All previously-flagged blocking issues in the nucleus layer have been addressed. Remaining observations are limited to error-code naming inconsistencies and a return-semantics mismatch in the not-yet-wired event gate functions — neither causes current incorrect behavior.

enginelib/src/events/mod.rs warrants a second look when the transport layer is wired: BeforeTaskBlock* gate functions return true=blocked while auth check functions return true=allowed.

Important Files Changed

Filename Overview
enginelib/src/api.rs Core ServerAPI with RocksDB init, load(), populate(), init(), and reap_expired(). DB open now uses expect() with a diagnostic message. reap_expired correctly clears dedup entries without touching persisted records.
enginelib/src/nucleus/submit.rs Now correctly returns Result<String, Error> with the generated task_id. Verifies bytes before persisting.
enginelib/src/nucleus/cancel.rs Correctly cancels the lease (not the task): removes from leased_tasks, try_send back to channel; falls back to clearing dedup on channel full/closed so load() can recover.
enginelib/src/nucleus/complete.rs Writes f: record before deleting t: record (crash-safe ordering). clear_dedup closure called on every exit path.
enginelib/src/nucleus/query.rs Well-designed operator query surface: cursor-paginated Scan (O(limit)), range-tombstone PurgePrefix, O(1) point ops.
enginelib/src/nucleus/lease.rs Correctly clones the receiver out of the DashMap guard before awaiting, preventing shard lock held across async recv.
enginelib/src/nucleus/renew.rs Correctly resets given_at to extend TTL. Returns TaskTypeNotFound when there are no active leases — misleading vs cancel()'s TaskNotFound for the same condition.
enginelib/src/events/mod.rs BeforeTaskBlock* gate functions return cancelled (true=blocked) while CheckAdminAuth/CheckAuth return true=allowed — inconsistent semantics to address when transport is wired.
enginelib/src/lib.rs error module is now pub, resolving the previous private-module-in-public-signature issue.

Reviews (5): Last reviewed commit: "grptile issue" | Re-trigger Greptile

Comment thread enginelib/src/nucleus/submit.rs Outdated
Comment thread enginelib/src/nucleus/cancel.rs
Comment thread enginelib/src/nucleus/submit.rs Outdated
Comment thread enginelib/src/api.rs Outdated
Comment thread enginelib/src/lib.rs
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
enginelib/src/event.rs (1)

126-132: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Clone the handler list before dispatching.

event_handler_registry.event_handlers.get(&id) keeps a DashMap read guard alive for the whole callback loop. If a handler re-enters the registry and calls register_handler, that write will wait on the guard held here and can self-deadlock. Pull the Arcs out first, then invoke handlers from the cloned list.

🤖 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 `@enginelib/src/event.rs` around lines 126 - 132, Clone the handler Arc list
before dispatching in the event handling loop around
event_handler_registry.event_handlers.get(&id). Release the DashMap read guard
before iterating, then apply the existing cancellation filtering and
handler.handle(event) calls to the cloned list so callbacks can safely register
handlers reentrantly.
🧹 Nitpick comments (3)
enginelib/src/api.rs (2)

47-51: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

DB::open(...).unwrap() panics with no context on startup failure.

A locked/corrupted DB, missing permissions, or a stale lock file will abort the process with an opaque panic. Prefer surfacing the path and error:

Proposed change
-        let db = Arc::new(rust_rocksdb::DB::open(&opts, path).unwrap());
+        let db = Arc::new(
+            rust_rocksdb::DB::open(&opts, path)
+                .unwrap_or_else(|err| panic!("Failed to open RocksDB at {path}: {err}")),
+        );
🤖 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 `@enginelib/src/api.rs` around lines 47 - 51, Update the database
initialization around DB::open to handle startup failures without an opaque
unwrap panic. Preserve the "./engine_db" path, but propagate or report the open
error with both the path and underlying error details before terminating
according to the existing startup error-handling pattern.

153-153: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Unresolved TODO on queue capacity.

The bounded(8192) capacity is hard-coded with a TODO to make it configurable/unbounded. A full channel will block load() senders (handled) but also caps in-flight tasks per type. Want me to wire this to Config or open a tracking issue?

🤖 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 `@enginelib/src/api.rs` at line 153, Resolve the queue-capacity TODO in the
channel initialization within the API setup: replace the hard-coded 8192 value
with the appropriate Config-backed capacity, or make the channel unbounded if
that is the intended behavior. Remove the TODO comment and ensure the existing
load sender and receiver flow continues using the selected channel.
enginelib/src/prelude.rs (1)

13-13: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Delete the stale AdminAuthEvent prelude export comment The symbol is still used internally, but it is no longer part of the public prelude, so the commented-out re-export can be removed.

🤖 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 `@enginelib/src/prelude.rs` at line 13, Remove the stale commented-out
AdminAuthEvent re-export from the prelude module; leave the internal
AdminAuthEvent implementation and usages unchanged.
🤖 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 `@engine/src/bin/server.rs`:
- Around line 4-6: Update the main server startup flow around ServerAPI::init so
the process remains running by restoring the enginelib::server::RPC construction
and RPC::run invocation. If this entrypoint is intentionally a stub, replace the
commented code with an explicit stub that preserves the intended non-exiting
behavior.

In `@enginelib/src/api.rs`:
- Around line 166-169: The LeasedTaskQueue background reaper currently sleeps
for the full lease TTL, delaying startup and allowing reclamation to lag
significantly. Update the loop surrounding LeasedTaskQueue::reap_expired to run
at a fraction of LEASE_TTL_SECS, such as one-sixth of the TTL, while preserving
the existing periodic reaping behavior.

In `@enginelib/src/nucleus/cancel.rs`:
- Around line 6-28: Update cancel() so the successful api.db.delete(...)
operation also contributes to removed, allowing cancellation of tasks that exist
only in RocksDB to return Ok(()). Preserve the existing leased_tasks and
task_queue removal checks and continue returning TaskNotFound only when none of
those removals or the database deletion indicates a record was removed.

In `@enginelib/src/nucleus/complete.rs`:
- Around line 32-45: Make the finished-record persistence and pending-record
deletion in the complete flow atomic by replacing the separate api.db.put and
api.db.delete calls with a single WriteBatch commit containing both operations.
Preserve the existing error propagation through Error::io_error, and only clear
the dedup entry after the atomic batch succeeds so partial failure leaves the
pending state recoverable.

---

Outside diff comments:
In `@enginelib/src/event.rs`:
- Around line 126-132: Clone the handler Arc list before dispatching in the
event handling loop around event_handler_registry.event_handlers.get(&id).
Release the DashMap read guard before iterating, then apply the existing
cancellation filtering and handler.handle(event) calls to the cloned list so
callbacks can safely register handlers reentrantly.

---

Nitpick comments:
In `@enginelib/src/api.rs`:
- Around line 47-51: Update the database initialization around DB::open to
handle startup failures without an opaque unwrap panic. Preserve the
"./engine_db" path, but propagate or report the open error with both the path
and underlying error details before terminating according to the existing
startup error-handling pattern.
- Line 153: Resolve the queue-capacity TODO in the channel initialization within
the API setup: replace the hard-coded 8192 value with the appropriate
Config-backed capacity, or make the channel unbounded if that is the intended
behavior. Remove the TODO comment and ensure the existing load sender and
receiver flow continues using the selected channel.

In `@enginelib/src/prelude.rs`:
- Line 13: Remove the stale commented-out AdminAuthEvent re-export from the
prelude module; leave the internal AdminAuthEvent implementation and usages
unchanged.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: b0e4239c-c0b9-440d-8fe7-ca69692e9b69

📥 Commits

Reviewing files that changed from the base of the PR and between 02c2369 and 3f26f58.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (48)
  • .github/workflows/rust.yml
  • Cargo.toml
  • engine/Cargo.toml
  • engine/build.rs
  • engine/proto/engine.proto
  • engine/src/bin/client.rs
  • engine/src/bin/packer.rs
  • engine/src/bin/server.rs
  • engine/src/lib.rs
  • enginelib/Cargo.toml
  • enginelib/src/api.rs
  • enginelib/src/config.rs
  • enginelib/src/error.rs
  • enginelib/src/event.rs
  • enginelib/src/events/admin_auth_event.rs
  • enginelib/src/events/auth_event.rs
  • enginelib/src/events/before_task_acquire_event.rs
  • enginelib/src/events/before_task_block_acquire_event.rs
  • enginelib/src/events/before_task_block_execute_event.rs
  • enginelib/src/events/before_task_block_publish_event.rs
  • enginelib/src/events/before_task_execute_event.rs
  • enginelib/src/events/before_task_publish_event.rs
  • enginelib/src/events/cgrpc_event.rs
  • enginelib/src/events/mod.rs
  • enginelib/src/events/server_task_block_acquired_event.rs
  • enginelib/src/events/server_task_block_created_event.rs
  • enginelib/src/events/server_task_block_published_event.rs
  • enginelib/src/events/server_task_created_event.rs
  • enginelib/src/events/task_acquired_event.rs
  • enginelib/src/events/task_block_acquired_event.rs
  • enginelib/src/lib.rs
  • enginelib/src/nucleus/cancel.rs
  • enginelib/src/nucleus/complete.rs
  • enginelib/src/nucleus/lease.rs
  • enginelib/src/nucleus/mod.rs
  • enginelib/src/nucleus/query.rs
  • enginelib/src/nucleus/renew.rs
  • enginelib/src/nucleus/submit.rs
  • enginelib/src/plugin.rs
  • enginelib/src/prelude.rs
  • enginelib/src/task.rs
  • enginelib/tests/event_tests.rs
  • rfc/rfc1000.md
  • rfc/rfc1001.md
  • rfc/rfc1002.md
  • rfc/rfc1003.md
  • rfc/rfc1004.md
  • rfc/rfc1005.md
💤 Files with no reviewable changes (18)
  • engine/build.rs
  • rfc/rfc1005.md
  • rfc/rfc1004.md
  • enginelib/src/events/before_task_publish_event.rs
  • rfc/rfc1000.md
  • engine/src/lib.rs
  • engine/src/bin/client.rs
  • rfc/rfc1002.md
  • rfc/rfc1003.md
  • enginelib/tests/event_tests.rs
  • enginelib/src/events/task_acquired_event.rs
  • engine/src/bin/packer.rs
  • engine/proto/engine.proto
  • enginelib/src/events/before_task_acquire_event.rs
  • enginelib/src/events/before_task_execute_event.rs
  • enginelib/src/events/server_task_created_event.rs
  • rfc/rfc1001.md
  • .github/workflows/rust.yml

Comment thread engine/src/bin/server.rs
Comment on lines +4 to +6
let mut api = ServerAPI::init();
// let server = enginelib::server::RPC::new(&api);
// server.run();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check CI for a deny-warnings policy that would fail on unused_mut/unused_variables
fd -H -t f 'rust.yml' .github
rg -nP -C2 '(-D\s*warnings|RUSTFLAGS|deny\(warnings\)|clippy)' .github || echo "No explicit deny-warnings found"

Repository: voltaero/engine

Length of output: 212


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- engine/src/bin/server.rs ---'
cat -n engine/src/bin/server.rs

echo
echo '--- .github/workflows/rust.yml ---'
cat -n .github/workflows/rust.yml

Repository: voltaero/engine

Length of output: 1502


main exits immediately. With RPC::run() still commented out, the binary returns as soon as ServerAPI::init() completes, so the server never stays up. Restore the run call or leave an explicit stub if this entrypoint is intentional.

🤖 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 `@engine/src/bin/server.rs` around lines 4 - 6, Update the main server startup
flow around ServerAPI::init so the process remains running by restoring the
enginelib::server::RPC construction and RPC::run invocation. If this entrypoint
is intentionally a stub, replace the commented code with an explicit stub that
preserves the intended non-exiting behavior.

Comment thread enginelib/src/api.rs
Comment on lines +166 to +169
std::thread::spawn(move || {
loop {
std::thread::sleep(std::time::Duration::from_secs(3600));
LeasedTaskQueue::reap_expired(&dapi);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reap interval equals the lease TTL — expiry can lag up to ~2× TTL.

The background loop sleeps LEASE_TTL_SECS (3600s) and only then reaps, so an expired lease is reclaimed anywhere from 0 to ~3600s after it expires (and the first sweep is delayed a full hour after startup). If timely reclamation matters for task re-leasing, run the sweep at a fraction of the TTL (e.g. TTL/6).

🤖 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 `@enginelib/src/api.rs` around lines 166 - 169, The LeasedTaskQueue background
reaper currently sleeps for the full lease TTL, delaying startup and allowing
reclamation to lag significantly. Update the loop surrounding
LeasedTaskQueue::reap_expired to run at a fraction of LEASE_TTL_SECS, such as
one-sixth of the TTL, while preserving the existing periodic reaping behavior.

Comment on lines +6 to +28
pub fn cancel(api: Arc<ServerAPI>, task_type: Identifier, task_id: String) -> Result<(), Error> {
let mut removed = false;
if let Some(mut leases) = api.leased_tasks.tasks.get_mut(&task_type) {
let before = leases.len();
leases.retain(|lease| lease.stored_task.task_id != task_id);
removed = leases.len() != before;
}

// Delete the persisted record before clearing the dedup entry so a
// concurrent load() cannot re-enqueue the cancelled task.
api.db
.delete(task_key(&task_type, &task_id))
.map_err(|err| Error::io_error(format!("Failed to delete task record: {err}")))?;
if let Some(queue) = api.task_queue.tasks.get(&task_type) {
removed |= queue.2.remove(&task_id).is_some();
}

if removed {
Ok(())
} else {
Err(Error::not_found("TaskNotFound"))
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

cancel() can return TaskNotFound even though it just deleted a real record.

removed is derived only from leased_tasks membership and the queue dedup set. A task that was submit()-ted but not yet scanned into memory by load() exists only in RocksDB — api.db.delete(...) will remove it, but removed never reflects that, so the function still returns Err(NotFound) despite the successful cancellation.

🔧 Proposed fix: derive `removed` from the DB delete outcome too
 pub fn cancel(api: Arc<ServerAPI>, task_type: Identifier, task_id: String) -> Result<(), Error> {
     let mut removed = false;
     if let Some(mut leases) = api.leased_tasks.tasks.get_mut(&task_type) {
         let before = leases.len();
         leases.retain(|lease| lease.stored_task.task_id != task_id);
         removed = leases.len() != before;
     }

     // Delete the persisted record before clearing the dedup entry so a
     // concurrent load() cannot re-enqueue the cancelled task.
-    api.db
-        .delete(task_key(&task_type, &task_id))
-        .map_err(|err| Error::io_error(format!("Failed to delete task record: {err}")))?;
+    let key = task_key(&task_type, &task_id);
+    let existed = api
+        .db
+        .get(&key)
+        .map_err(|err| Error::io_error(format!("Failed to check task record: {err}")))?
+        .is_some();
+    api.db
+        .delete(&key)
+        .map_err(|err| Error::io_error(format!("Failed to delete task record: {err}")))?;
+    removed |= existed;
     if let Some(queue) = api.task_queue.tasks.get(&task_type) {
         removed |= queue.2.remove(&task_id).is_some();
     }
📝 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
pub fn cancel(api: Arc<ServerAPI>, task_type: Identifier, task_id: String) -> Result<(), Error> {
let mut removed = false;
if let Some(mut leases) = api.leased_tasks.tasks.get_mut(&task_type) {
let before = leases.len();
leases.retain(|lease| lease.stored_task.task_id != task_id);
removed = leases.len() != before;
}
// Delete the persisted record before clearing the dedup entry so a
// concurrent load() cannot re-enqueue the cancelled task.
api.db
.delete(task_key(&task_type, &task_id))
.map_err(|err| Error::io_error(format!("Failed to delete task record: {err}")))?;
if let Some(queue) = api.task_queue.tasks.get(&task_type) {
removed |= queue.2.remove(&task_id).is_some();
}
if removed {
Ok(())
} else {
Err(Error::not_found("TaskNotFound"))
}
}
pub fn cancel(api: Arc<ServerAPI>, task_type: Identifier, task_id: String) -> Result<(), Error> {
let mut removed = false;
if let Some(mut leases) = api.leased_tasks.tasks.get_mut(&task_type) {
let before = leases.len();
leases.retain(|lease| lease.stored_task.task_id != task_id);
removed = leases.len() != before;
}
// Delete the persisted record before clearing the dedup entry so a
// concurrent load() cannot re-enqueue the cancelled task.
let key = task_key(&task_type, &task_id);
let existed = api
.db
.get(&key)
.map_err(|err| Error::io_error(format!("Failed to check task record: {err}")))?
.is_some();
api.db
.delete(&key)
.map_err(|err| Error::io_error(format!("Failed to delete task record: {err}")))?;
removed |= existed;
if let Some(queue) = api.task_queue.tasks.get(&task_type) {
removed |= queue.2.remove(&task_id).is_some();
}
if removed {
Ok(())
} else {
Err(Error::not_found("TaskNotFound"))
}
}
🤖 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 `@enginelib/src/nucleus/cancel.rs` around lines 6 - 28, Update cancel() so the
successful api.db.delete(...) operation also contributes to removed, allowing
cancellation of tasks that exist only in RocksDB to return Ok(()). Preserve the
existing leased_tasks and task_queue removal checks and continue returning
TaskNotFound only when none of those removals or the database deletion indicates
a record was removed.

Comment on lines +32 to +45
// Persist the finished record before deleting the pending one so a crash
// between the two writes never loses the result.
api.db
.put(finished_task_key(&task_type, &task_id), task_bytes)
.map_err(|err| Error::io_error(format!("Failed to persist finished task: {err}")))?;
api.db
.delete(task_key(&task_type, &task_id))
.map_err(|err| Error::io_error(format!("Failed to delete task record: {err}")))?;

// Clear the dedup entry last so a concurrent load() cannot re-enqueue a task
// whose pending record is already gone.
if let Some(queue) = api.task_queue.tasks.get(&task_type) {
queue.2.remove(&task_id);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Make the finish+cleanup write atomic to avoid a stuck duplicate record on partial failure.

put(finished_task_key) and delete(task_key) are separate calls. If the put succeeds but the delete fails, complete() returns Err, yet the lease was already dropped a few lines earlier — so a retry will fail with TaskNotLeased, and the stale pending record is left behind with no self-healing path (only recoverable via cancel() or an operator Query::PurgePrefix).

🔧 Proposed fix using an atomic WriteBatch
-    api.db
-        .put(finished_task_key(&task_type, &task_id), task_bytes)
-        .map_err(|err| Error::io_error(format!("Failed to persist finished task: {err}")))?;
-    api.db
-        .delete(task_key(&task_type, &task_id))
-        .map_err(|err| Error::io_error(format!("Failed to delete task record: {err}")))?;
+    let mut batch = rust_rocksdb::WriteBatch::default();
+    batch.put(finished_task_key(&task_type, &task_id), task_bytes);
+    batch.delete(task_key(&task_type, &task_id));
+    api.db
+        .write(&batch)
+        .map_err(|err| Error::io_error(format!("Failed to persist finished task: {err}")))?;
📝 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
// Persist the finished record before deleting the pending one so a crash
// between the two writes never loses the result.
api.db
.put(finished_task_key(&task_type, &task_id), task_bytes)
.map_err(|err| Error::io_error(format!("Failed to persist finished task: {err}")))?;
api.db
.delete(task_key(&task_type, &task_id))
.map_err(|err| Error::io_error(format!("Failed to delete task record: {err}")))?;
// Clear the dedup entry last so a concurrent load() cannot re-enqueue a task
// whose pending record is already gone.
if let Some(queue) = api.task_queue.tasks.get(&task_type) {
queue.2.remove(&task_id);
}
// Persist the finished record before deleting the pending one so a crash
// between the two writes never loses the result.
let mut batch = rust_rocksdb::WriteBatch::default();
batch.put(finished_task_key(&task_type, &task_id), task_bytes);
batch.delete(task_key(&task_type, &task_id));
api.db
.write(&batch)
.map_err(|err| Error::io_error(format!("Failed to persist finished task: {err}")))?;
// Clear the dedup entry last so a concurrent load() cannot re-enqueue a task
// whose pending record is already gone.
if let Some(queue) = api.task_queue.tasks.get(&task_type) {
queue.2.remove(&task_id);
}
🤖 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 `@enginelib/src/nucleus/complete.rs` around lines 32 - 45, Make the
finished-record persistence and pending-record deletion in the complete flow
atomic by replacing the separate api.db.put and api.db.delete calls with a
single WriteBatch commit containing both operations. Preserve the existing error
propagation through Error::io_error, and only clear the dedup entry after the
atomic batch succeeds so partial failure leaves the pending state recoverable.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@enginelib/src/nucleus/cancel.rs`:
- Around line 16-34: Validate that the task type exists in api.task_queue.tasks
before entering the lease-removal block in the cancellation flow. Update the
code around the stored_task extraction and queue lookup so
task_queue.tasks.get(&task_type) returns TaskTypeNotFound without mutating
leased_tasks; preserve the existing lease removal and requeue behavior after
validation succeeds.
- Around line 5-46: Narrow the `cancel` documentation and contract to leased
tasks only, explicitly stating that queued-but-unleased tasks are not removed;
update the `Query::Delete` guidance to direct pending queued-task deletion
through the appropriate separate path rather than `cancel` or `complete`.
Preserve the existing lease removal and requeue behavior in `cancel`.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 88dca659-412a-4567-be7b-1caf78129adf

📥 Commits

Reviewing files that changed from the base of the PR and between 3f26f58 and 208015f.

📒 Files selected for processing (5)
  • enginelib/src/api.rs
  • enginelib/src/lib.rs
  • enginelib/src/nucleus/cancel.rs
  • enginelib/src/nucleus/query.rs
  • enginelib/src/nucleus/submit.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • enginelib/src/lib.rs
  • enginelib/src/api.rs

Comment on lines +5 to +46
/// Cancels the *lease* on a task, not the task itself: removes it from the lease
/// list and resends it into the queue so another worker can pick it up.
///
/// The persisted record is never touched, and the task_id stays in the dedup set
/// the whole time, so no concurrent `load()` can enqueue a duplicate. The requeue
/// is a non-blocking `try_send` so there is no await window in which the lease is
/// gone but the task isn't yet back in the channel: on success the task moves
/// straight from "leased" to "queued"; if the channel is full or closed we clear
/// the dedup entry instead, dropping the task back to "persisted only" so a later
/// `load()` recovers it. Either way the task is never stranded.
pub fn cancel(api: Arc<ServerAPI>, task_type: Identifier, task_id: String) -> Result<(), Error> {
// Remove the lease, capturing the stored task so we can requeue it.
let stored_task = {
let mut leases = api
.leased_tasks
.tasks
.get_mut(&task_type)
.ok_or(Error::not_found("TaskNotFound"))?;
let idx = leases
.iter()
.position(|lease| lease.stored_task.task_id == task_id)
.ok_or(Error::not_found("TaskNotFound"))?;
leases.swap_remove(idx).stored_task
};

let queue = api
.task_queue
.tasks
.get(&task_type)
.ok_or(Error::not_found("TaskTypeNotFound"))?;

// Non-blocking requeue: no await means the lease removal and the requeue
// can't be split by an async cancellation.
match queue.0.try_send((*stored_task).clone()) {
// Queued again; task_id stays in the dedup set (still in-flight).
Ok(()) => Ok(()),
// Channel full/closed: clear the dedup entry so the still-persisted
// record is re-enqueued by a later load(). Never left stranded.
Err(_) => {
queue.2.remove(&task_id);
Ok(())
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -B2 -A15 '\bfn cancel\b|\bcancel\(' enginelib/src/nucleus/mod.rs enginelib/src -g '!nucleus/cancel.rs'

Repository: voltaero/engine

Length of output: 2488


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== nucleus mod outline ==\n'
ast-grep outline enginelib/src/nucleus/mod.rs --view expanded || true

printf '\n== cancel.rs ==\n'
cat -n enginelib/src/nucleus/cancel.rs | sed -n '1,120p'

printf '\n== query.rs relevant lines ==\n'
rg -n -A12 -B8 'Delete|cancel|complete|pending task|queued or leased|dedup' enginelib/src/nucleus/query.rs

printf '\n== nucleus mod references to cancel ==\n'
rg -n -A8 -B8 '\bcancel\b' enginelib/src/nucleus/mod.rs enginelib/src -g '!enginelib/src/nucleus/cancel.rs' -g '!**/target/**'

Repository: voltaero/engine

Length of output: 10104


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== file list in nucleus ==\n'
git ls-files enginelib/src/nucleus

printf '\n== transport/admin caller search ==\n'
rg -n -A4 -B4 'TaskNotFound|TaskTypeNotFound|cancel\(' enginelib/src -g '!enginelib/src/nucleus/cancel.rs' -g '!**/target/**'

Repository: voltaero/engine

Length of output: 4067


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== inspect mod.rs and query.rs sizes ==\n'
wc -l enginelib/src/nucleus/mod.rs enginelib/src/nucleus/query.rs enginelib/src/nucleus/cancel.rs

printf '\n== mod.rs slice ==\n'
cat -n enginelib/src/nucleus/mod.rs | sed -n '1,220p'

printf '\n== query.rs slice ==\n'
cat -n enginelib/src/nucleus/query.rs | sed -n '1,220p'

Repository: voltaero/engine

Length of output: 9952


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== search for API handlers exposing cancel/complete/delete ==\n'
rg -n -A6 -B6 '\b(cancel|complete|delete)\b' enginelib/src -g '!**/target/**' | sed -n '1,220p'

Repository: voltaero/engine

Length of output: 8849


cancel() only releases leased tasks back into the queue; it does not remove queued-but-unleased tasks. The Query::Delete docs still point callers at cancel/complete for pending tasks, so the contract should be narrowed or the queued case handled separately.

🤖 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 `@enginelib/src/nucleus/cancel.rs` around lines 5 - 46, Narrow the `cancel`
documentation and contract to leased tasks only, explicitly stating that
queued-but-unleased tasks are not removed; update the `Query::Delete` guidance
to direct pending queued-task deletion through the appropriate separate path
rather than `cancel` or `complete`. Preserve the existing lease removal and
requeue behavior in `cancel`.

Comment on lines +16 to +34
// Remove the lease, capturing the stored task so we can requeue it.
let stored_task = {
let mut leases = api
.leased_tasks
.tasks
.get_mut(&task_type)
.ok_or(Error::not_found("TaskNotFound"))?;
let idx = leases
.iter()
.position(|lease| lease.stored_task.task_id == task_id)
.ok_or(Error::not_found("TaskNotFound"))?;
leases.swap_remove(idx).stored_task
};

let queue = api
.task_queue
.tasks
.get(&task_type)
.ok_or(Error::not_found("TaskTypeNotFound"))?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Lease is removed before the queue existence check — can strand a task.

leases.swap_remove(idx) (lines 17-28) mutates state before the fallible task_queue.tasks.get(&task_type) lookup (lines 30-34). If that lookup returns Err(TaskTypeNotFound), the lease is already gone, the task was never requeued, and the dedup entry is untouched — the task is now neither leased, queued, nor recoverable by a later load(). This directly contradicts the function's own doc comment ("Either way the task is never stranded", lines 12-14). Currently only reachable if task_queue and leased_tasks diverge for a task_type (they're populated together in ServerAPI::populate), but the fix is cheap and removes a latent landmine.

🔧 Proposed fix: validate queue existence before mutating lease state
 pub fn cancel(api: Arc<ServerAPI>, task_type: Identifier, task_id: String) -> Result<(), Error> {
+    let queue = api
+        .task_queue
+        .tasks
+        .get(&task_type)
+        .ok_or(Error::not_found("TaskTypeNotFound"))?;
+
     // Remove the lease, capturing the stored task so we can requeue it.
     let stored_task = {
         let mut leases = api
             .leased_tasks
             .tasks
             .get_mut(&task_type)
             .ok_or(Error::not_found("TaskNotFound"))?;
         let idx = leases
             .iter()
             .position(|lease| lease.stored_task.task_id == task_id)
             .ok_or(Error::not_found("TaskNotFound"))?;
         leases.swap_remove(idx).stored_task
     };
 
-    let queue = api
-        .task_queue
-        .tasks
-        .get(&task_type)
-        .ok_or(Error::not_found("TaskTypeNotFound"))?;
-
     // Non-blocking requeue: no await means the lease removal and the requeue
     // can't be split by an async cancellation.
     match queue.0.try_send((*stored_task).clone()) {
📝 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
// Remove the lease, capturing the stored task so we can requeue it.
let stored_task = {
let mut leases = api
.leased_tasks
.tasks
.get_mut(&task_type)
.ok_or(Error::not_found("TaskNotFound"))?;
let idx = leases
.iter()
.position(|lease| lease.stored_task.task_id == task_id)
.ok_or(Error::not_found("TaskNotFound"))?;
leases.swap_remove(idx).stored_task
};
let queue = api
.task_queue
.tasks
.get(&task_type)
.ok_or(Error::not_found("TaskTypeNotFound"))?;
let queue = api
.task_queue
.tasks
.get(&task_type)
.ok_or(Error::not_found("TaskTypeNotFound"))?;
// Remove the lease, capturing the stored task so we can requeue it.
let stored_task = {
let mut leases = api
.leased_tasks
.tasks
.get_mut(&task_type)
.ok_or(Error::not_found("TaskNotFound"))?;
let idx = leases
.iter()
.position(|lease| lease.stored_task.task_id == task_id)
.ok_or(Error::not_found("TaskNotFound"))?;
leases.swap_remove(idx).stored_task
};
// Non-blocking requeue: no await means the lease removal and the requeue
// can't be split by an async cancellation.
match queue.0.try_send((*stored_task).clone()) {
🤖 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 `@enginelib/src/nucleus/cancel.rs` around lines 16 - 34, Validate that the task
type exists in api.task_queue.tasks before entering the lease-removal block in
the cancellation flow. Update the code around the stored_task extraction and
queue lookup so task_queue.tasks.get(&task_type) returns TaskTypeNotFound
without mutating leased_tasks; preserve the existing lease removal and requeue
behavior after validation succeeds.

Comment thread enginelib/src/nucleus/complete.rs
@IGN-Styly
IGN-Styly merged commit 2502cff into main Jul 21, 2026
8 of 9 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jul 21, 2026
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