refactor(core): 034 Phase 1 — mechanical debt cleanup (#129, #132)#136
Merged
Conversation
…cated .link() Database<A> was a thin wrapper over AimDb referenced only by the TokioDatabase/EmbassyDatabase type aliases, which themselves had no users in the workspace. RecordRegistrar::link() has been deprecated since 0.2.0 with zero remaining callers. Part of docs/design/034 Phase 1 (#132, task 3). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every DbError variant now has one shape on all targets: context fields are alloc::string::String unconditionally (the crate already requires alloc everywhere), and Display/Error derive from thiserror on every target (thiserror 2.x is no_std-capable). This deletes: - all #[cfg]-gated dual fields (field: String vs _field: ()) and the _field: () placeholders - the hand-written no_std Display impl (numeric-code table) — no_std builds now produce the same error messages as std builds - every dual construction branch in builder.rs, typed_record.rs, graph.rs, time.rs, connector.rs, the adapters, and the MQTT/KNX connectors Helper constructors (runtime_error, permission_denied, record_key_not_found, new missing_configuration) are un-gated, single body, and public. thiserror moves from optional (remote-access) to a mandatory no_std dependency. BREAKING (no_std only): field renames _key: () -> key: String etc.; no_std Display output changed from 'Error 0xNNNN' codes to full messages. Closes #129 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ocks
std::sync::Arc, std::boxed::Box etc. are re-exports of the alloc types,
and the crate has an unconditional crate-root 'extern crate alloc'. One
unconditional 'use alloc::...' therefore works on every target:
- replace all dual #[cfg(feature = "std")]/#[cfg(not(...))] import
pairs in builder.rs, router.rs, typed_record.rs, record_id.rs and
buffer/{traits,writer,cfg}.rs
- drop the redundant per-module 'extern crate alloc;' declarations
(the ones inside ext_macros.rs expansions stay: they expand into
other crates)
- context.rs: collapse the character-for-character duplicated std /
no_std RuntimeContext impl blocks and the dual Arc field type into
one alloc-based impl; un-gate from_runtime/create_runtime_context
and the runtime() getter
The std::sync::Mutex vs spin::Mutex alias in typed_record.rs and the
std::io import in error.rs stay gated — those are real platform
differences.
Part of docs/design/034 Phase 1 (#132, task 1).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gates
New #[macro_use] mod log defines log_debug!/log_info!/log_warn!/
log_error!: they forward to the matching tracing event macro when the
'tracing' feature is on and expand to a no-op that borrows the
arguments otherwise, so call sites compile identically under every
feature combination. All 62 per-call-site #[cfg(feature = "tracing")]
gates are gone; the only remaining gate is inside src/log.rs itself.
defmt is deliberately not folded into the macro: most call sites use
{:?} with types that don't implement defmt::Format, and adding defmt
output would be a behavior change. router.rs keeps its explicit
paired defmt gates.
Structural collapses: transform/join.rs now computes output_key/
input_keys unconditionally (build-time one-shot allocations) instead
of cfg-gated shadow variables; builder.rs inlines builder.scheme()
into the macro args; remote/stream.rs drops tracing's structured-field
syntax (record = %key) for plain format args, which the shim macro
(and defmt, if ever) can express.
Part of docs/design/034 Phase 1 (#132, task 2).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 5-tuple type alias forced every consumer to destructure positionally. OutboundRoute is now a struct with named fields (topic, consumer, serializer, config, topic_provider); construction in collect_outbound_routes and the two consumers (session/client.rs, session/pump.rs) use field names. Part of docs/design/034 Phase 1 (#132, task 5). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ConsumerTrait::subscribe_any has been infallible since M14 — the DbResult wrapper only existed 'so connector code stays unchanged'. The future now resolves to Box<dyn AnyReader> directly and the two callers (session/pump.rs, session/client.rs) lose their dead Err arms. build() looked up each topo-order key with an O(n) scan over by_key.keys() and then resolved the same key again for its RecordId. StringKey implements Borrow<str> with content-based Hash, so a single get_key_value(key_str) returns both in O(1) — the unreachable RecordKeyNotFound branch goes away with it. The O(n) records.iter().position() in configure() is intentionally left alone: it is build-time-only over small N, and the builder internals are restructured by #130/#133. Part of docs/design/034 Phase 1 (#132, task 6). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Since the session-engine refactor (030/033) the only tokio:: references in aimdb-core/src are inside #[cfg(test)] modules and doc comments. The optional [dependencies] tokio (net, io-util, sync, time) enabled by the std feature pulled tokio into every std build of a crate that advertises runtime neutrality. The dev-dependency gains 'sync' (used by tests/session_engine.rs, previously satisfied by feature unification with the optional dependency). Part of docs/design/034 Phase 1 (#132, task 4). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st builds Fallout from the DbError unification: the mock reader's 'mock'.to_string() needs alloc::string::ToString in scope when the test harness builds with --no-default-features --features alloc. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 1 of the 034 technical-debt review — the mechanical, zero-behavior-change cleanup. One PR for the whole phase (per the "one PR per phase" plan), structured as one commit per work item so it reviews cleanly. Breaking changes are accepted (decision 2026-06-09).
Closes #129. Closes #132.
Net: +177 / −638 lines across core, adapters, and the MQTT/KNX connectors.
Commits (one per work item)
delete dead Database wrapper, adapter aliases, .link()Database<A>,TokioDatabase/EmbassyDatabase, deprecatedRecordRegistrar::link()(all zero-user)unify DbError on alloc::String (#129)thiserrorderivesDisplay/Errorunconditionally; no_std numeric-codeDisplaytable deletedunify std/alloc imports; merge RuntimeContext implsuse std::… / use alloc::…pairs → oneuse alloc::…; duplicatedRuntimeContextimpl blocks mergedcrate-private log_*! macros replace tracing gates#[cfg(feature = "tracing")]gates →log_debug!/log_info!/log_warn!/log_error!struct-ify OutboundRouteflatten subscribe_any; O(1) by_key lookupsubscribe_anyinfallible; O(n)keys().find()→ O(1)get_key_valuedrop vestigial tokio dependencystdno longer pullstokiointo every build (tests cover it via dev-deps)changelog entriesimport ToString in buffer traits test moduleBreaking changes (accepted)
DbError:_field: ()placeholders become the realStringfields;Displaynow prints full messages instead ofError 0xNNNNcodes;DbErrornow implementscore::error::Error. Std variant shapes/messages unchanged.Database<A>,TokioDatabase,EmbassyDatabase,RecordRegistrar::link().ConsumerTrait::subscribe_anyreturnsBox<dyn AnyReader>(wasDbResult<…>).OutboundRouteis a struct, not a 5-tuple.aimdb-core'sstdfeature no longer enables atokiodependency;thiserroris now a mandatory (no_std) dependency;DbError::{runtime_error, permission_denied, record_key_not_found}are nowpub(+ newmissing_configuration).Verification
make check— fmt, clippy (full feature matrix), test,test-embedded(thumbv7em-none-eabihf),test-wasm,deny— all passmake examples— all example crates build_field: ()placeholders, nouse std::{dual imports, notracinggates outsidesrc/log.rs,cargo treeshows no tokio in normal deps, noDatabase/.link()references.Out of scope (other issues)
#130 (builder de-
Any, registrar lifetimes), #131 (Rremoval), #133 (panic-free validation), #134 (MQTT knobs out of core).🤖 Generated with Claude Code