Skip to content

Rust async hygiene: ingest verbs are async fn but never await actual yields #334

@willwashburn

Description

@willwashburn

Context

Every public ingest verb is async fn, but the bodies are sync filesystem walks, sync rusqlite INSERTs, and sync parsers. None of them .await anything that actually yields to the runtime.

Affected verbs (crates/relayburn-sdk/src/ingest/ingest.rs):

  • ingest_all (:159)
  • ingest_claude_projects (:194)
  • ingest_codex_sessions (:213)
  • ingest_opencode_sessions (:232)
  • reingest_missing_content (in reingest.rs)
  • LedgerHandle::ingest

The CLI presenters (commands/ingest.rs, commands/run.rs) wrap each call in a fresh single-thread tokio runtime, and commands/mcp_server.rs already wraps in spawn_blocking. So today the async annotation is a tax — each call has to set up a future, but it's just sync code in a costume.

The two reasonable directions

A. Drop the async. Make these all fn. Callers that need to schedule work off the runtime use spawn_blocking themselves (the mcp_server already does). This matches the actual semantics.

B. Keep async and actually yield. Wrap the rusqlite operations in tokio::task::spawn_blocking, switch filesystem walks to tokio::fs. This makes the async annotation honest at the cost of more Send bounds and a small latency hit per yield.

A is simpler and matches what the code already does. B is more honest if the watch loop ever needs to be cancellable mid-tick (it isn't today — watch_loop.rs polls between ticks, not during).

Proposed direction

Pick A unless there's a near-term need for B. Document the choice in the SDK README so the next person isn't tempted to "fix" it back.

Adjacent

  • watch_loop.rs:197-203 run_ingest_tick is a one-line wrapper over ingest().await. Either way, delete it.
  • watch_loop.rs:182-191 has a "belt-and-braces" in_flight.lock().await after handle.await that's dead under the existing invariant.

References

  • crates/relayburn-sdk/src/ingest/ingest.rs:159, 194, 213, 232
  • crates/relayburn-sdk/src/ingest/watch_loop.rs:182-191, 197-203
  • Ingest review notes from the May 2026 Rust review.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions