Skip to content

120 no std aimx server dispatch port cross cutting anyrecord recordmetadatatracker de std#125

Merged
lxsaah merged 3 commits into
mainfrom
120-no_std-aimx-server-dispatch-port-cross-cutting-anyrecord-recordmetadatatracker-de-std
Jun 4, 2026
Merged

120 no std aimx server dispatch port cross cutting anyrecord recordmetadatatracker de std#125
lxsaah merged 3 commits into
mainfrom
120-no_std-aimx-server-dispatch-port-cross-cutting-anyrecord-recordmetadatatracker-de-std

Conversation

@lxsaah

@lxsaah lxsaah commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

no_std AimX server (dispatch) port — cross-cutting AnyRecord + RecordMetadataTracker de-std

Closes #120. Follow-up to #39 / design doc 041.

What this does

The Phase 6 foundation (#39) landed the generic session connectors, the aimdb-uds-connector crate, and a no_std AimX codec — i.e. the embedded client path (a sensor dialing a gateway). What stayed std-only was the AimX server dispatch (AimxDispatch/AimxSession).

This PR lifts that dispatch — and the central record API it reaches into — onto no_std + alloc, so an MCU can now serve a host (e.g. "board answers a host over serial": record.list / get / set / drain / subscribe), not just dial one.

Tracing the dependency to the bottom, this is a cross-cutting refactor of core's record API, not a mechanical re-gate.

Approach: a dedicated remote-access feature

Rather than overload json-serialize, the server data model now sits behind a new feature:

remote-access = ["json-serialize", "thiserror"]   # transitively enabled by `std`

This cleanly separates the two embedded opt-ins:

Feature Gives you Path
json-serialize JSON value codec — record.latest()?.as_json() embedded client
remote-access record metadata + introspection, the type-erased JSON read/write/subscribe API, the wire protocol/config/security/error types, and the AimX server dispatch (with connector-session) embedded server

std pulls in remote-access transitively, so std builds are unaffected.

Changes by area

aimdb-core — the cross-cutting de-std

  • Re-gated stdremote-access: the AnyRecord trait methods (collect_metadata / latest_json / subscribe_json / set_from_json), the JsonBufferReader trait, the remote module, and the AimDb/AimDbInner JSON API (list_records / try_latest_as_json / set_record_from_json).
  • De-std'd the dispatch: std::collections::HashMap/HashSethashbrown, std::sync::Arcalloc::sync::Arc.
  • De-std'd the remote module: AimxConfig.socket_path PathBufString, SecurityPolicy HashSethashbrown, thiserror pulled with default-features = false, From<std::io::Error> for RemoteError kept behind a std cfg.
  • Removed RecordMetadataTracker (an Arc<Mutex<…>> + Arc<AtomicBool> + SystemTime::now() on every produce()). The surviving writable bit is now a single portable_atomic::AtomicBool field on TypedRecord; collect_metadata reads the type name + flag directly with no shared state.
  • DbError::{runtime_error, permission_denied, record_key_not_found} pub(crate) constructors — let the JSON/remote paths write one error expression across std (message carried) and no_std (unit placeholder), replacing the inline #[cfg] splits.
  • graph serde derives (RecordOrigin / GraphNode / GraphEdge / EdgeType) moved from the std gate to the serde feature (always on with alloc) so RecordMetadata serializes on no_std.

Runtime-neutral wall clock

RecordMetadataTracker tracked created_at / last_update via SystemTime — which has no no_std equivalent. Introduced an abstraction on the runtime adapter instead:

  • aimdb-executor: new TimeOps::unix_time(&self) -> Option<(u64, u32)> — absolute wall-clock time, distinct from the monotonic now(). Default impl returns None (a bare MCU with no RTC).
  • aimdb-tokio-adapter: implements it from the OS clock (SystemTime::now()).
  • aimdb-embassy-adapter: EmbassyAdapter::set_unix_time(now_unix_secs) anchors a process-global u32 (Unix seconds at boot); unix_time() then derives (secs, nanos) from monotonic uptime + the anchor, returning None until the device learns the real time (NTP / GPS / host handshake).

aimdb-uds-connector

  • UdsServer::new / socket_path take impl Into<String> (was impl Into<PathBuf>); the internal bind goes through std::path::Path::new(&socket_path) — same synchronous remove-stale → bindset_permissions behavior.

Verification target (Makefile test-embedded)

Added the full no_std server cross-check, plus remote-access test/clippy lines:

cargo check --package aimdb-core --target thumbv7em-none-eabihf \
  --no-default-features --features "alloc,connector-session,remote-access"

Note: this differs from the literal command in #120, which used json-serialize. Under the new feature layout that builds only the codec — the dispatch is gated on remote-access. The Makefile uses the correct feature set.

Tooling fallout

  • aimdb-mcp: list_records, the records resource, and query_schema no longer emit created_at / last_update (core stopped tracking them).
  • aimdb-cli / aimdb-client: test fixtures updated for the RecordMetadata::new signature and the socket_path: String change (test-only).

Breaking changes

  • RecordMetadata loses created_at / last_update; RecordMetadata::new drops its created_at parameter; with_last_update / with_last_update_opt removed. AimX record.list (and MCP / CLI output derived from it) no longer carry those two fields.
  • AimxConfig.socket_path is now String (was PathBuf); AimxConfig::socket_path(...) / UdsServer::new(...) take impl Into<String>. &str / String callers are unaffected; &Path / PathBuf callers must convert (e.g. path.to_str().unwrap()).

Verification

All green:

  • cargo check -p aimdb-core --no-default-features --features "alloc,remote-access" (host)
  • cargo check -p aimdb-core --no-default-features --features "alloc,connector-session,remote-access" --target thumbv7em-none-eabihf — the AimX dispatch cross-compiles (the issue's target)
  • cargo check -p aimdb-core --features "std,tracing,metrics"
  • cargo check -p aimdb-embassy-adapter --target thumbv7em-none-eabihf
  • cargo test -p aimdb-core --no-default-features --features "alloc,remote-access" — 7 passed
  • cargo test -p aimdb-core --lib --features "std" remote:: — 18 passed
  • No dangling references to the removed RecordMetadataTracker / created_at / last_update across either workspace; aimdb-pro's demo .socket_path("…") still compiles (&str: Into<String>).

Checklist (from #120)

  • Re-gate the AnyRecord JSON + metadata methods off the std gate
  • De-std RecordMetadataTracker (removed entirely; timestamp tracking dropped, writableportable_atomic::AtomicBool)
  • De-std the remote module (socket_pathString, HashSethashbrown, gate thiserror / io::Error)
  • Re-gate the AimDb JSON API off std
  • Re-gate AimxDispatch/AimxSession to connector-session + remote-access; std::collectionshashbrown, std::sync::Arcalloc::sync::Arc
  • Add the embedded dispatch check to the Makefile test-embedded target

Out of scope (separate follow-ups, per doc 041)

aimdb-serial-connector, aimdb-tcp-connector, host client AimxConnection::connect_over / connect_url, and the cli/mcp --connect <url> / AIMDB_CONNECT resolver.

lxsaah added 3 commits June 4, 2026 17:09
- Updated error handling in `remote/error.rs` to streamline conversion from `DbError` to `RemoteError`, utilizing `ToString` for message generation.
- Removed `created_at` and `last_update` fields from `RecordMetadata` in `remote/metadata.rs`, simplifying metadata structure and focusing on essential fields.
- Adjusted `RecordMetadata` construction and associated methods to reflect the removal of timestamp fields.
- Modified `AnyRecord` trait methods to align with the new metadata structure, ensuring compatibility with remote access features.
- Enhanced `aimx/dispatch.rs` and `aimx/mod.rs` to support `no_std + alloc` configurations, removing `std` dependencies where applicable.
- Updated UDS server implementation in `uds-connector` to accept `String` for socket paths, improving flexibility.
- Cleaned up JSON serialization tests in CLI tools to remove references to removed timestamp fields.
- Ensured all changes maintain compatibility with existing functionality while improving code clarity and maintainability.
…` fields, addition of `unix_time` methods, and changes to `UdsServer` constructor for no_std compatibility.
… fields, and changes to `AimxConfig.socket_path` for no_std compatibility
@lxsaah lxsaah self-assigned this Jun 4, 2026
@lxsaah lxsaah merged commit 276497f into main Jun 4, 2026
7 checks passed
@lxsaah lxsaah deleted the 120-no_std-aimx-server-dispatch-port-cross-cutting-anyrecord-recordmetadatatracker-de-std branch June 4, 2026 17:47
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.

no_std AimX server (dispatch) port — cross-cutting AnyRecord + RecordMetadataTracker de-std

1 participant