Skip to content

feat(aimx)!: exact-topic subscribes send a late-join snapshot (#438) - #440

Merged
lxsaah merged 1 commit into
mainfrom
feat/aimx-exact-snapshots
Nov 7, 2026
Merged

lxsaah merged 1 commit into
mainfrom
feat/aimx-exact-snapshots

Conversation

@lxsaah

@lxsaah lxsaah commented Nov 7, 2026

Copy link
Copy Markdown
Member

Closes #438. Part of #422.

What changes

An exact-topic AimX subscribe over UDS, TCP or serial now starts with the record's current value as a snap frame (last: true), followed by events from seq 2. Wildcard subscribes and WebSocket already work this way. A record with no current value sends no snapshot. That covers records with nothing written yet and SpmcRing buffers.

The duplicate this also fixes

A new SingleLatest reader starts on the record's current value, on tokio (mark_changed) and on embassy (Watch). So:

  • exact subscribes already received the current value, but as a plain first event;
  • wildcard subscribes received it twice, once as the snapshot and again as the first event.

AimxSession::record_stream now opens the reader and then reads the snapshot, in that order. The stream then drops leading updates stamped at or before the snapshot. A write after the snapshot has a later stamp, so it is still delivered as an event. The snapshot is read with try_latest_as_json_bytes, the same path record.get uses. The engine calls subscribe and then snapshots, so subscribe stores the snapshots and snapshots() hands them over.

Client, CLI, MCP

  • watch::arm + await_updates: no change. The snapshot's stamp equals the baseline, so it is filtered out. armed_watch_sees_only_the_write_after_it still passes for SingleLatest, ring and Mailbox.
  • aimdb watch <record>: the current value now arrives as a snapshot, followed by the 📸 snapshot complete line. It came as the first event before, so --count counts it as before, and --new still skips it. The README and CHANGELOG are updated.
  • MCP: no tool subscribes, so nothing changes.
  • I left out the optional simplification of arm (dropping the record.get). It can be a follow-up.

Tests

New test exact_subscribe_sends_the_current_value_once in aimdb-client/tests/aimx_session.rs:

  • an exact subscribe gets one snapshot that closes the burst;
  • a wildcard matching only that record gets the same snapshot (topic, value and ts);
  • after a write, every stream's next update is that write;
  • a ring and an unwritten record get no snapshot.

With the head filter turned off, the test fails on the duplicate value.

Locally:

  • client, CLI, core (std,tracing), UDS, TCP (_test-tokio) and serial (std) tests;
  • clippy on core (alloc,remote,connector-session and std,tracing,observability), client, CLI and MCP;
  • the Cortex-M fixture clippy;
  • fmt.

Compatibility

Wire change: AimX exact-topic subscribers now receive a snap frame before the first event. In-repo clients already handle snap. The core CHANGELOG entry is marked as a wire change.

🤖 Generated with Claude Code

An exact-topic AimX subscribe now sends the record's current value as a
`snap` frame, as wildcard subscribes and WebSocket already do. A record
with no current value (none written yet, or an `SpmcRing`) sends none.

Each record's stream is opened first and its snapshot read right after;
the stream then drops leading updates stamped at or before the snapshot.
A fresh SingleLatest reader starts on the current value, so without this
the value arrived twice: as the snapshot and again as the first event
(already the case on wildcard subscribes).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@lxsaah
lxsaah merged commit 0a51963 into main Nov 7, 2026
9 checks passed
@lxsaah
lxsaah deleted the feat/aimx-exact-snapshots branch November 7, 2026 21:05
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.

AimX exact-topic subscribes send a late-join snapshot, like wildcards and WebSocket

1 participant