Skip to content

refactor(core)!: remove runtime type parameter R from the object graph — non-generic AimDb/TypedRecord/RuntimeContext (R-removal part 2) #131

@lxsaah

Description

@lxsaah

Context

Part 2 of 2 of the runtime-decoupling work from docs/design/034-technical-debt-review.md (§3.2, §3.3) — builds on #130 (dyn-safe RuntimeOps + builder de-erasure). This completes the program started in designs 028/029: Producer<T>/Consumer<T> are already R-free; this issue removes R from the rest of the object graph and deletes the dyn Any plumbing that existed only to escape it.

Breaking changes are explicitly fine — desired, even. The aim is a clean structure. No compatibility shims, no phantom-parameter aliases, no deprecation cycles. Downstream code (examples, tools, connectors) is updated mechanically in the same change series.

Target state

The runtime is a value with a capability interface (Arc<dyn RuntimeOps> from #130), not a type parameter. The only generic parameter left on the user-facing object graph is T — the record types, where static typing actually earns its keep.

Tasks

1. Non-generic RuntimeContext

  • RuntimeContext becomes a concrete struct wrapping Arc<dyn RuntimeOps>; delete the duplicated std/no_std impl blocks and the panicking extract_from_any.
  • Known observable break: ctx.time().now() returns u64 nanos instead of R::Instant (e.g. embassy_time::Instant). Call sites that store instants switch to nanos or unix_time().

2. Strip R from the record graph

  • TypedRecord<T, R>TypedRecord<T>; stored service closures take (Producer<T>/Consumer<T>, RuntimeContext) instead of Arc<dyn Any + Send + Sync>.
  • RecordRegistrar<'a, T, R>RecordRegistrar<'a, T>; source()/tap() become inherent methods (no more per-adapter downcasting wrappers).
  • TransformDescriptor<T, R>TransformDescriptor<T>; build fns receive Arc<dyn RuntimeOps> + Arc<AimDb>.

3. Strip R from the database and connectors

  • AimDb<R>AimDb; delete runtime_any(); runtime_arc() returns Arc<dyn RuntimeOps>.
  • ConnectorBuilder<R>ConnectorBuilder (all in-tree connectors already implement it blanket-for-all-R and never use R).
  • Consumer/producer factories take &AimDb instead of Arc<dyn core::any::Any> + downcast-or-panic.
  • Delete the RuntimeForProfiling marker-trait workaround in lib.rs (profiling calls now_nanos()).

4. Delete JoinFanInRuntime

  • Replace the GAT-based JoinFanInRuntime/JoinQueue/JoinSender/JoinReceiver family and the three per-adapter join_queue.rs files with one bounded async-channel queue in core — the same primitive the session engine already uses on tokio, Embassy, and WASM.

5. Dissolve ext_macros.rs

  • With RuntimeContext non-generic and the lifetime fix from refactor(executor/core): dyn-safe RuntimeOps trait + de-erase builder internals & registrar lifetimes (R-removal part 1) #130, TokioRecordRegistrarExt/EmbassyRecordRegistrarExt/wasm equivalents lose their reason to exist. Primary user API becomes plain, rustdoc-visible inherent methods.
  • Open decision — .buffer(BufferCfg): buffer construction is the one genuinely adapter-specific piece left. Options:
    (a) keep one tiny per-adapter extension trait for .buffer() only, or
    (b) have the builder take a buffer factory at .runtime() time, or
    (c) runtime-neutral buffer impls in core (largest win — deletes ~2.5k adapter lines — but SPMC-ring lag semantics need a hand-rolled implementation; likely a follow-up issue).
    Recommendation: (a) or (b) here, (c) as follow-up.

6. Data plane: erase to bytes, not dyn Any (stretch goal — may split out)

  • Outbound: fuse the serializer into the typed side so connectors receive (topic, Payload) already serialized — deletes AnyReader::recv_any + SerializerFn(&dyn Any) downcasts per message.
  • Inbound: store Fn(&[u8]) -> Result<(), Error> closures that deserialize and produce in one typed step — deletes ProducerTrait::produce_any.

Acceptance criteria

  • No core::any import remains in aimdb-core outside TypeId-based registry lookup and DynBuffer::as_any
  • grep -rn "extract_from_any\|runtime_any\|RuntimeForProfiling\|JoinFanInRuntime" aimdb-*/src returns nothing
  • R/runtime type parameters appear in no public core type except via Arc<dyn RuntimeOps>
  • ext_macros.rs deleted; adapter crates reduced to executor glue + RuntimeOps impl (+ buffer wiring per the §5 decision)
  • All examples, connectors, tools compile after mechanical signature updates; behavior unchanged (make check, make examples)
  • Changelog documents the breaks: AimDb<R>AimDb, RuntimeContext signature, now() → nanos, ext-trait removal

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions