Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
98 changes: 98 additions & 0 deletions .agent/notes/counter-poll-audit-core.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# rivetkit-core counter-poll audit

Date: 2026-04-22
Story: US-027

## Scope

Searched `rivetkit-rust/packages/rivetkit-core/src/` for:

- `loop { ... sleep(Duration::from_millis(_)).await; ... }`
- `loop { ... tokio::time::sleep(...).await; ... }`
- `while ... { ... sleep(Duration::from_millis(_)).await; ... }`
- `AtomicUsize`, `AtomicU32`, `AtomicU64`, and `AtomicBool` fields with async waiters

## Converted polling sites

- `registry.rs::Registry::handle_fetch`
- Classification before: polling.
- Problem: after an HTTP request, the rearm task checked `can_sleep() == ActiveHttpRequests` and slept in 10 ms slices until the envoy HTTP request counter reached zero.
- Fix: added `SleepController::wait_for_http_requests_idle(...)` and `ActorContext::wait_for_http_requests_idle()`, both backed by the existing `AsyncCounter` zero-notify registration on `work.idle_notify`.
- Coverage: added `http_request_idle_wait_uses_zero_notify` to prove the waiter wakes on decrement-to-zero without advancing a polling interval.

## Event-driven sites

- `actor/state.rs::wait_for_save_request`
- Classification: event-driven.
- Uses `save_completion: Notify`; waiters arm `notified()` before re-checking `save_completed_revision`.

- `actor/state.rs::wait_for_pending_writes` / `wait_for_in_flight_writes`
- Classification: event-driven.
- Tracked persist tasks are awaited directly; KV writes use `in_flight_writes` plus `write_completion: Notify` on decrement-to-zero.

- `actor/sleep.rs::wait_for_sleep_idle_window`
- Classification: event-driven.
- Arms `work.idle_notify` before checking HTTP request, keep-awake, internal keep-awake, and websocket callback counters.

- `actor/sleep.rs::wait_for_shutdown_tasks`
- Classification: event-driven.
- Uses `AsyncCounter::wait_zero(deadline)` for shutdown tasks and websocket callbacks, plus `prevent_sleep_notify` for the prevent-sleep flag.

- `actor/sleep.rs::wait_for_internal_keep_awake_idle`
- Classification: event-driven.
- Uses `AsyncCounter::wait_zero(deadline)`.

- `actor/sleep.rs::wait_for_http_requests_drained`
- Classification: event-driven.
- Uses the envoy `AsyncCounter::wait_zero(deadline)` after registering zero notifications on `work.idle_notify`.

- `actor/context.rs::wait_for_destroy_completion`
- Classification: event-driven.
- Uses `destroy_completion_notify` and re-checks `destroy_completed`.

- `actor/queue.rs::next_batch`, `wait_for_names`, and `wait_for_names_available`
- Classification: event-driven.
- Message waits use queue `Notify`; active wait counts are RAII-owned by `ActiveQueueWaitGuard`.

## Monotonic sequence / one-shot atomics

- `actor/state.rs` save revisions (`revision`, `save_request_revision`, `save_completed_revision`)
- Classification: monotonic sequence with notify-backed awaiters.

- `actor/task.rs` inspector attach count
- Classification: event-triggering counter.
- The counter is owned by `InspectorAttachGuard`; transitions enqueue lifecycle events instead of polling.

- `actor/schedule.rs::local_alarm_epoch`
- Classification: monotonic sequence guard.
- Spawned local alarm tasks check the epoch once after the timer fires to ignore stale work.

- `actor/schedule.rs::driver_alarm_cancel_count`
- Classification: diagnostic/test counter.
- No production awaiter.

- `inspector/mod.rs` revision counters and active counts
- Classification: snapshot/revision counters.
- Subscribers are notified through listener callbacks; no async counter polling.

- `kv.rs` stats counters
- Classification: diagnostic/test counters.
- No async awaiter in production code.

## Non-counter sleep loops

- `registry.rs::wait_for_engine_health`
- Classification: retry backoff.
- Sleeps between external HTTP health-check attempts, not waiting on shared memory.

- `actor/state.rs::persist_state` and pending-save task
- Classification: intentional debounce timers.
- Sleeps until a configured save delay elapses, not polling a counter.

- `actor/schedule.rs::reschedule_local_alarm`
- Classification: timer scheduling.
- Sleeps until the next alarm timestamp, then checks the monotonic epoch to avoid stale dispatch.

- Protocol read/write loops in `registry.rs` and `sqlite.rs`
- Classification: codec loops.
- No async sleep or shared-state polling.
81 changes: 81 additions & 0 deletions .agent/notes/counter-poll-audit-napi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# rivetkit-napi counter-poll audit

Date: 2026-04-22
Story: US-029

## Scope

Searched `rivetkit-typescript/packages/rivetkit-napi/src/` for:

- `loop { ... sleep(Duration::from_millis(_)) ... }`
- `while ... { ... sleep(Duration::from_millis(_)) ... }`
- `tokio::time::sleep`, `std::thread::yield_now`, and retry loops
- `AtomicUsize`, `AtomicU32`, `AtomicU64`, and `AtomicBool` fields with waiters
- `Mutex<usize>`, `Mutex<bool>`, and similar scalar locks
- polling-shaped exports such as `poll_*`

## Converted polling sites

- `cancel_token.rs::lock_registry_for_test`
- Classification before: test-only spin polling.
- Problem: tests serialized access to the global cancel-token registry by spinning on an `AtomicBool` with `std::thread::yield_now()`.
- Fix: replaced the spin gate with a test-only `parking_lot::Mutex<()>`, returning a real guard from `lock_registry_for_test()`.
- Coverage: existing cancel-token cleanup tests still exercise the same serialized registry path.

## Event-driven sites

- `bridge_actor.rs` response waits
- Classification: event-driven.
- Uses per-request `oneshot` channels in `ResponseMap`; no counter or sleep-loop polling.

- `napi_actor_events.rs::drain_tasks`
- Classification: event-driven.
- Pumps already-registered tasks, then awaits `JoinSet::join_next()` until the set is empty; no timed polling interval.

- `napi_actor_events.rs` callback tests with `Notify`
- Classification: event-driven test gates.
- Uses `tokio::sync::Notify` and `oneshot` channels for deterministic ordering.

- Queue wait bindings in `queue.rs`
- Classification: event-driven through core.
- Delegates to `rivetkit-core` queue waits and optional cancellation tokens; no local counter polling.

## Monotonic sequence / diagnostic atomics

- `cancel_token.rs::NEXT_CANCEL_TOKEN_ID`
- Classification: monotonic ID generator.
- No waiter.

- `cancel_token.rs::active_token_count`
- Classification: test diagnostic snapshot.
- Tests read it after guarded operations complete; no async waiter or sleep-loop polls it.

- `actor_context.rs::next_websocket_callback_region_id`
- Classification: monotonic region ID generator.
- No waiter.

- `actor_context.rs::ready` and `started`
- Classification: lifecycle flags.
- Read synchronously to validate lifecycle transitions; no sleep-loop waiter.

- `napi_actor_events.rs` test `AtomicU64` / `AtomicBool` values
- Classification: test observation flags.
- Tests combine these with `oneshot`, `Notify`, or task joins; no timed polling loop waits on them.

## Non-counter sleep / polling-shaped sites

- `napi_actor_events.rs::with_timeout` and tests
- Classification: timeout assertion.
- Uses `tokio::time::timeout` or a bounded `select!` branch to prove a future is still pending, not to poll shared state.

- `napi_actor_events.rs` test `sleep(Duration::from_secs(60))`
- Classification: pending-work fixture.
- The sleep is intentionally cancelled by an abort token; no shared counter is polled.

- `queue.rs` and `schedule.rs` `Duration::from_millis(...)`
- Classification: user-supplied timeout/delay conversion.
- Converts JS options to core durations; no polling loop.

- `cancel_token.rs::poll_cancel_token`
- Classification: explicit JS cancellation polling surface, not a counter waiter.
- This is a public NAPI sync read used by the TS abort-signal bridge. It reads a cancellation token's state once and does not loop or wait in Rust.
63 changes: 63 additions & 0 deletions .agent/notes/counter-poll-audit-sqlite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# rivetkit-sqlite counter-poll audit

Date: 2026-04-22
Story: US-028

## Scope

Searched `rivetkit-rust/packages/rivetkit-sqlite/src/` for:

- `loop { ... sleep(Duration::from_millis(_)) ... }`
- `while ... { ... sleep(Duration::from_millis(_)) ... }`
- `tokio::time::sleep`, `std::thread::sleep`
- `AtomicUsize`, `AtomicU32`, `AtomicU64`, and `AtomicBool` fields with waiters
- `Mutex<usize>`, `Mutex<bool>`, and similar scalar locks

## Converted polling sites

- None in this sweep.
- The US-007 `MockProtocol` counter/gate fix is still present: `awaited_stage_responses` uses `AtomicUsize` plus `stage_response_awaited: Notify`, and `mirror_commit_meta` uses `AtomicBool`.
- No remaining `Mutex<usize>` / `Mutex<bool>` scalar wait gates were found in `src/`.

## Event-driven sites

- `vfs.rs::MockProtocol::wait_for_stage_responses`
- Classification: event-driven test waiter.
- Uses `awaited_stage_responses: AtomicUsize` paired with `stage_response_awaited: Notify`.
- Wait is bounded by `tokio::time::timeout(Duration::from_secs(1), ...)`.

- `vfs.rs::MockProtocol::commit_finalize`
- Classification: event-driven test gate.
- Uses `finalize_started: Notify` and `release_finalize: Notify`; no polling loop.

## Monotonic sequence / diagnostic atomics

- `vfs.rs::NEXT_STAGE_ID`, `NEXT_TEMP_AUX_ID`, and test `TEST_ID`
- Classification: monotonic ID generators.
- No waiter.

- `vfs.rs::commit_atomic_count`
- Classification: diagnostic/test observation counter.
- Tests read it after operations complete; no async waiter or sleep-loop polls it.

- `vfs.rs` performance counters (`resolve_pages_total`, `resolve_pages_cache_hits`, `resolve_pages_fetches`, `pages_fetched_total`, `prefetch_pages_total`, `commit_total`, timing totals)
- Classification: metrics/snapshot counters.
- Tests read snapshots after controlled operations; no wait-for-zero or wait-for-threshold loop.

- `vfs.rs` test `keep_reading: AtomicBool`
- Classification: cross-thread control flag.
- The reader thread intentionally runs SQLite reads until compaction completes; it is not waiting for the flag to become true and has no sleep-based polling interval.

## Non-counter sleep loops

- `vfs.rs::vfs_sleep`
- Classification: SQLite VFS implementation callback.
- Implements SQLite's `xSleep` contract by sleeping for the requested microseconds.

- `vfs.rs::DirectEngineHarness::open_engine`
- Classification: external resource retry backoff.
- Retries `RocksDbDatabaseDriver::new(...)` with a 10 ms sleep because the temporary DB directory can be briefly busy between test runs. It does not poll an in-process counter/flag/map size.

- `query.rs` statement loops and `vfs.rs::sqlite_step_statement`
- Classification: SQLite stepping loops.
- These loop over `sqlite3_step(...)` until `SQLITE_DONE` or an error; they do not sleep or poll shared state.
1 change: 0 additions & 1 deletion .agent/notes/driver-engine-static-test-order.md

This file was deleted.

73 changes: 0 additions & 73 deletions .agent/notes/driver-test-fix-audit.md

This file was deleted.

Loading
Loading