Skip to content

Make AimX remote access spawn free#118

Merged
lxsaah merged 9 commits into
mainfrom
114-make-aimx-remote-access-spawn-free
May 27, 2026
Merged

Make AimX remote access spawn free#118
lxsaah merged 9 commits into
mainfrom
114-make-aimx-remote-access-spawn-free

Conversation

@lxsaah
Copy link
Copy Markdown
Contributor

@lxsaah lxsaah commented May 26, 2026

Make AimX remote-access and WS client connector spawn-free

Closes #114. Implements design 030; finishes the "Group 4" work design 028 deferred.

Why

After #88 every runtime.spawn(...) was gone — except nine bare tokio::spawn calls in AimX (3) and the WS client connector (6). They didn't depend on the Spawn trait (gated via #[cfg(feature = "std")]), so the trait could ship, but the dynamic-fan-out shape needed a nested FuturesUnordered rewrite that was out of scope for #88. This PR does that rewrite. Zero tokio::spawn remain in aimdb-core or the connectors; cancellation collapses to dropping the future.

What changed

AimX (aimdb-core/src/remote/)

  • supervisor.rs — accept loop owns a FuturesUnordered<BoxFuture> of per-connection handlers (select! { biased; }). max_connections (previously declared-but-unread) is now actually enforced: over-cap connections are refused pre-handshake.
  • handler.rs — each record.subscribe pushes a future onto a per-connection FuturesUnordered. The two-task chain per subscription collapses into one run_subscription future.
  • stream.rs (new) — stream_record_updates adapts a JsonBufferReader into a Stream<Item = serde_json::Value> via unfold. Drop to cancel.
  • AimDb::subscribe_record_updates deleted — only caller was the AimX handler.

Cancellation: Notify, not AtomicBool
record.unsubscribe fires an Arc<Notify> raced against stream.next() in a biased select!. Cancellation is immediate even on a quiet record — the previous atomic-flag design could pin a buffer reader indefinitely until the next event.

WS client connector
All six tokio::spawn sites collapse into one infrastructure future owning a FuturesUnordered. The reconnect watcher sends NewLoops { write_sink, read_stream, write_rx } over an mpsc to the outer future instead of spawning. WsClientConnectorImpl::connect() now returns Result<(Self, BoxFuture), String>; internal-only.

Breaking changes

  • AimxConfig::subscription_queue_size removed → replace with .max_subs_per_connection(n) (default 32) or delete the call.
  • AimxConfig::max_connections (default 16) is now actually enforced.
  • AimX Welcome.max_subscriptions now reports max_subs_per_connection (32) instead of the dead subscription_queue_size (100).
  • record.subscribe response no longer carries queue_size; result is { "subscription_id": "..." }.

Tests

New #[cfg(all(test, feature = "std"))] tests in handler.rs / stream.rs:

  • dropping_subs_set_drops_subscription_stream — drops the FuturesUnordered, verifies the underlying stream is dropped.
  • dropping_subs_set_drops_inner_stream_state — stronger version with a real channel-backed stream.
  • unsubscribe_terminates_subscription_immediatelynotify_one() exits the future parked on stream.next() with no further values needed.
  • unfold_skips_lag_and_terminates_on_closed — covers BufferLagged skip and BufferClosed exit.

make check / make all green.

Docs

Out of scope

Lifting #[cfg(feature = "std")] on AimX — shape is now runtime-agnostic, but transport (UDS, tokio I/O) is still std-only.

- Updated the WS client connector to eliminate the use of tokio::spawn for background tasks.
- Introduced a nested FuturesUnordered to manage the read, write, keepalive, and reconnect loops.
- The connect method now returns a tuple containing the connector and its associated future.
- Enhanced the reconnect watcher to send new loop information to the outer future, allowing for seamless reconnections without spawning new tasks.
- Updated documentation to reflect changes in the connector's architecture and task management.
@lxsaah lxsaah linked an issue May 26, 2026 that may be closed by this pull request
6 tasks
@lxsaah lxsaah self-assigned this May 27, 2026
@lxsaah lxsaah added the 🏗️ core Core engine work label May 27, 2026
@lxsaah lxsaah marked this pull request as ready for review May 27, 2026 19:05
@lxsaah lxsaah requested a review from Copilot May 27, 2026 19:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR completes the “spawn-free” refactor for AimX remote access and the WebSocket client connector by removing remaining tokio::spawn fan-out points and driving per-connection / per-subscription (and per-reconnect) loops via nested FuturesUnordered owned by a single infrastructure future, with cancellation via dropping futures.

Changes:

  • Refactors AimX supervisor + per-connection handler to own nested FuturesUnordered sets (no per-connection / per-sub tokio::spawn), and enforces max_connections / max_subs_per_connection.
  • Introduces stream_record_updates helper returning a Stream for record updates, and removes the old AimDb::subscribe_record_updates spawn-based helper.
  • Refactors WS client connector to return an infrastructure future that owns its background loops and uses an mpsc (NewLoops) to swap read/write loops on reconnect (no spawns).

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
examples/remote-access-demo/src/server.rs Updates demo config API usage to max_subs_per_connection.
examples/remote-access-demo/src/client.rs Updates demo client to new record.subscribe request/response shape (no queue_size).
docs/design/030-M13-aimx-remote-spawn-free.md New design doc describing the spawn-free implementation and rationale.
docs/design/028-M13-remove-spawn-trait.md Updates “Group 4” bridge-state discussion to point to design 030 as resolved.
aimdb-websocket-connector/src/client/connector.rs Reworks WS client connector to spawn-free nested FuturesUnordered model + reconnect loop handoff via NewLoops.
aimdb-websocket-connector/src/client/builder.rs Prepends the new connector infrastructure future to the returned futures list.
aimdb-websocket-connector/CHANGELOG.md Documents the WS client spawn-free refactor and connect signature change.
aimdb-core/src/remote/supervisor.rs Replaces per-connection tokio::spawn with a supervisor-owned FuturesUnordered and enforces max_connections.
aimdb-core/src/remote/stream.rs Adds stream_record_updates (unfold-based) stream adapter + tests.
aimdb-core/src/remote/mod.rs Updates module docs and exports stream module under std.
aimdb-core/src/remote/handler.rs Replaces per-subscription spawning with per-connection FuturesUnordered of subscription futures; unsubscribe uses Notify. Adds tests.
aimdb-core/src/remote/config.rs Removes subscription_queue_size, adds max_subs_per_connection, updates defaults/tests.
aimdb-core/src/builder.rs Deletes spawn-based AimDb::subscribe_record_updates helper.
aimdb-core/CHANGELOG.md Documents AimX spawn-free refactor + breaking config/protocol shape changes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread aimdb-core/src/remote/handler.rs Outdated
Comment thread aimdb-core/CHANGELOG.md Outdated
Comment thread docs/design/028-M13-remove-spawn-trait.md Outdated
Comment thread docs/design/030-M13-aimx-remote-spawn-free.md Outdated
Comment thread docs/design/030-M13-aimx-remote-spawn-free.md Outdated
Comment thread docs/design/030-M13-aimx-remote-spawn-free.md Outdated
Comment thread docs/design/030-M13-aimx-remote-spawn-free.md Outdated
Comment thread docs/design/030-M13-aimx-remote-spawn-free.md Outdated
Comment thread docs/design/030-M13-aimx-remote-spawn-free.md
lxsaah and others added 4 commits May 27, 2026 21:17
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@lxsaah lxsaah merged commit ab4abf6 into main May 27, 2026
5 checks passed
@lxsaah lxsaah deleted the 114-make-aimx-remote-access-spawn-free branch May 27, 2026 20:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🏗️ core Core engine work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make AimX remote-access spawn-free

2 participants