You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* feat(linkable): add allocation-free postcard `encode_into`
Add a caller-provided buffer API to `Linkable` while retaining the
existing from_bytes and to_bytes signatures for compatibility.
Introduce `LinkCodecError` and an optional into-slice serializer path in
core. Each outbound route owns one bounded reusable scratch buffer,
validates the returned length, and falls back to the existing `Vec`
serializer when the buffer is too small. Legacy and custom codecs keep
their previous behavior.
Generate a true postcard override using `postcard::to_slice` with a
256-byte preferred capacity. Extend codegen drift coverage for generated
connector wiring, exact and undersized buffers, Cortex-M compilation
and the JSON-free dependency graph.
Add an allocation-counting benchmark covering 10000 `encode_into` calls
with zero allocation calls and zero allocated bytes.
This removes the codec allocation only, connector-internal payload
copies remain outside the claim.
* refactor(linkable): reuse `SerializeError` for `encode_into`
Remove the newly introduced `LinkCodecError` and reuse the existing
`aimdb_core::connector::SerializeError` across the into-slice API,
postcard codegen, tests, benchmarks and documentation.
Keep the legacy Linkable `from_bytes`/`to_bytes` String errors unchanged
under the compatibility-first approach agreed in #177.
@@ -105,6 +106,10 @@ multi-step migration round-trip suite and a trybuild compile-fail harness.
105
106
106
107
### Added
107
108
109
+
-**Zero-allocation generated Postcard encoding (Issue #177).**`Linkable` gains a source-compatible `encode_into(&mut [u8])` fast path and generated Postcard records implement it with `postcard::to_slice`. Core reuses onebounded 256-byte scratch allocation per generated Postcard outbound route (raw builders choose their capacity) and falls back to the existing owned serializer when a value does not fit. The codec seam is gated by a 10,000-iteration allocation-counting bench (0 allocations, 0 bytes) plus
110
+
host, `no_std` Cortex-M, and codegen-drift tests. The claim intentionally excludes connector-internal payload copies and the existing boxed connector reader future. ([aimdb-core](aimdb-core/CHANGELOG.md),
-**Embassy MQTT client TLS — `mqtts://` for embedded, WP7 ([design 044](docs/design/044-embassy-mqtt-tls.md)).** The Embassy MQTT connector can now dial a broker over TLS 1.3 (`embedded-tls`, pure-Rust `rustpki` certificate verification with `rsa`/`p384` so public CA chains verify out of the box), with SNI/hostname verification, DNS resolution, and a connector-internal SNTP time source that gates the first handshake so certificate validity is always checked against real time. Behind the new `embassy-tls` feature; `MqttConnectorBuilder::new` picks the transport from the URL scheme (`mqtt://` plain, `mqtts://` TLS) and gains `with_tls(TlsOptions)` (entropy, record buffers, SNTP server) and `with_credentials(username, password)` (MQTT CONNECT auth, both transports). The plain `mqtt://` path is untouched. The `embassy-mqtt-connector-demo` example gains a `tls` feature demonstrating the full flow against the repo's `dev/mosquitto` bench broker. ([aimdb-mqtt-connector](aimdb-mqtt-connector/CHANGELOG.md))
109
114
- **Design 034 Phase 3 — sans-io KNX/IP tunneling engine shared by both transports (Issue #135, [review doc §3.7](docs/design/034-technical-debt-review.md)).** The entire tunneling lifecycle — CONNECT_REQUEST/RESPONSE handshake, TUNNELING_REQUEST/ACK sequence + pending-ACK bookkeeping, keepalive (CONNECTIONSTATE_REQUEST) scheduling, ACK-timeout sweeps, and reconnect-with-backoff — now lives **once**, in the new runtime-neutral `aimdb_knx_connector::tunnel` module (`no_std + alloc`, no tokio/embassy imports), driven as a poll-based state machine (events in, `Action`s out, `next_deadline()` for timer arming). `tokio_client.rs` (988 → ~530 lines incl. a new fake-gateway integration test) and `embassy_client.rs` (1,055 → ~450 lines) are reduced to socket shims; the previously untestable handshake/ACK/keepalive/reconnect paths now have 15 host-run unit tests plus a scripted localhost-UDP roundtrip test. Behavioral unifications: Embassy gains the 5 s CONNECT_RESPONSE timeout (previously waited forever), both shims reconnect on fatal socket errors, and the dead tokio-only per-publish ACK oneshot is dropped (it was always `None`); the CONNECT_REQUEST HPAI stays per-transport (`LocalEndpoint`: tokio = real bound address, Embassy = NAT mode). ([aimdb-knx-connector](aimdb-knx-connector/CHANGELOG.md))
**Why this change?** The new trait-based architecture provides:
641
+
630
642
- ✅ Symmetry with inbound routing (`ProducerTrait` ↔ `ConsumerTrait`)
631
643
- ✅ Testability (can mock `ConsumerTrait` without real records)
632
644
- ✅ Type safety via factory pattern (type capture at configuration time)
633
645
- ✅ Maintainability (connector logic stays in connector crate)
634
646
635
647
**Migration checklist for custom connectors:**
648
+
636
649
-[ ] Add `spawn_outbound_publishers()` method to connector implementation
637
650
-[ ] Call `db.collect_outbound_routes(protocol_name)` in `ConnectorBuilder::build()`
638
651
-[ ] Call `connector.spawn_outbound_publishers(db, routes)?` before returning
@@ -653,6 +666,7 @@ See [Connector Development Guide](docs/design/012-M5-connector-development-guide
653
666
### Added
654
667
655
668
#### Core Database (`aimdb-core`)
669
+
656
670
- Initial release of AimDB async in-memory database engine
657
671
- Type-safe record system using `TypeId`-based routing
658
672
- Three buffer types for different data flow patterns:
@@ -666,6 +680,7 @@ See [Connector Development Guide](docs/design/012-M5-connector-development-guide
666
680
- Remote access protocol (AimX v1) for cross-process introspection
667
681
668
682
#### Runtime Adapters
683
+
669
684
-**Tokio Adapter** (`aimdb-tokio-adapter`): Full-featured std runtime support
670
685
- Lock-free buffer implementations
671
686
- Configurable buffer capacities
@@ -676,6 +691,7 @@ See [Connector Development Guide](docs/design/012-M5-connector-development-guide
676
691
- Compatible with ARM Cortex-M targets
677
692
678
693
#### MQTT Connector (`aimdb-mqtt-connector`)
694
+
679
695
- Dual runtime support for both Tokio and Embassy
680
696
- Automatic consumer registration via builder pattern
681
697
- Topic mapping with QoS and retain configuration
@@ -685,6 +701,7 @@ See [Connector Development Guide](docs/design/012-M5-connector-development-guide
685
701
- Uses `mountain-mqtt` for embedded environments
686
702
687
703
#### Developer Tools
704
+
688
705
-**MCP Server** (`aimdb-mcp`): LLM-powered introspection and debugging
689
706
- Discover running AimDB instances
690
707
- Query record values and schemas
@@ -702,12 +719,14 @@ See [Connector Development Guide](docs/design/012-M5-connector-development-guide
702
719
- Clean error handling
703
720
704
721
#### Synchronous API (`aimdb-sync`)
722
+
705
723
- Blocking wrapper around async AimDB core
706
724
- Thread-safe synchronous record access
707
725
- Automatic Tokio runtime management
708
726
- Ideal for gradual migration from sync to async
709
727
710
728
#### Documentation & Examples
729
+
711
730
- Comprehensive README with architecture overview
712
731
- Individual crate documentation with examples
713
732
- 12 detailed design documents in `/docs/design`
@@ -718,6 +737,7 @@ See [Connector Development Guide](docs/design/012-M5-connector-development-guide
718
737
-`remote-access-demo`: Cross-process introspection server
719
738
720
739
#### Build & CI Infrastructure
740
+
721
741
- Comprehensive Makefile with color-coded output
722
742
- GitHub Actions workflows:
723
743
- Continuous integration (format, lint, test)
@@ -729,28 +749,33 @@ See [Connector Development Guide](docs/design/012-M5-connector-development-guide
729
749
- Dev container setup for consistent development environment
730
750
731
751
### Design Goals Achieved
752
+
732
753
- ✅ Sub-50ms latency for data synchronization
733
754
- ✅ Lock-free buffer operations
734
755
- ✅ Cross-platform support (MCU → edge → cloud)
735
756
- ✅ Type safety with zero-cost abstractions
736
757
- ✅ Protocol-agnostic connector architecture
737
758
738
759
### Known Limitations
760
+
739
761
- Kafka and DDS connectors planned for future releases
740
762
- CLI tool is currently skeleton implementation
741
763
- Performance benchmarks not yet included
742
764
- Limited to Unix domain sockets for remote access (no TCP yet)
743
765
744
766
### Dependencies
767
+
745
768
- Rust 1.75+ required
746
769
- Tokio 1.47+ for std environments
747
770
- Embassy 0.9+ for embedded environments
748
771
- See `deny.toml` for approved dependency licenses
749
772
750
773
### Breaking Changes
774
+
751
775
None (initial release)
752
776
753
777
### Migration Guide
778
+
754
779
Not applicable (initial release)
755
780
756
781
---
@@ -762,6 +787,7 @@ Not applicable (initial release)
762
787
AimDB v0.1.0 establishes the foundational architecture for async, in-memory data synchronization across MCU → edge → cloud environments. This release focuses on core functionality, dual runtime support, and developer tooling.
763
788
764
789
**Highlights:**
790
+
765
791
- 🚀 Dual runtime support: Works on both standard library (Tokio) and embedded (Embassy)
766
792
- 🔒 Type-safe record system eliminates runtime string lookups
767
793
- 📦 Three buffer types cover most data patterns
@@ -770,6 +796,7 @@ AimDB v0.1.0 establishes the foundational architecture for async, in-memory data
# B1 + B2 — latency (time/iter) and throughput (msgs/sec), one Criterion suite
57
62
cargo bench -p aimdb-bench --bench b1_b2_tokio
58
63
@@ -91,6 +96,7 @@ Criterion writes HTML reports to `target/criterion/`.
91
96
`b0_alloc_tokio` does not use Criterion. It runs a fixed warmup + batch cycle and writes JSON results to `aimdb-bench/target/bench-results/b0_alloc_tokio.json` (the path is anchored to the crate dir, so it is the same regardless of the directory you run from).
@@ -103,6 +109,9 @@ The committed baseline lives in `data/baselines/b0_alloc_tokio.json`. When a cha
103
109
104
110
`b0_alloc_embassy` mirrors this against the Embassy buffer backend and writes `data/baselines/b0_alloc_embassy.json` — also **0 allocs/msg** across all three profiles, confirming the Embassy `poll_recv` path is allocation-free on the host. The on-target B3 bench (`examples/embassy-bench-stm32h5`) re-checks the same 0-alloc claim against the real embedded allocator.
105
111
112
+
`b0_alloc_linkable` warms up for 1,000 iterations, then measures 10,000 generated-shape postcard `Linkable::encode_into` calls into one stack buffer.
113
+
The required result is **0 allocation calls and 0 allocated bytes**. It isolates the codec seam: `SerializedReader` still returns a boxed future, dynamic topics may allocate and connector implementations may copy payload ownership after the core pump lends them the scratch slice.
114
+
106
115
> **Embassy eager registration (design 039 F8/F9).** An Embassy `SpmcRing` reader registers its embassy `Subscriber` eagerly, at `subscribe()` time — matching Tokio's `broadcast` — so no separate priming step is needed before the first `push`.
107
116
108
117
**Noise reduction:** a `new_current_thread()` Tokio executor is used so there are no work-stealing threads and Tokio's scheduler does not allocate per-poll in the hot path.
@@ -127,5 +136,3 @@ Use them as a comparison point, not a regression gate. If they regress, `b0_allo
127
136
- Criterion p99 can vary ±5–10% on noisy CI runners. Use p50 medians for trend comparisons.
128
137
- Always specify `--release` or debug build consistently when comparing runs; optimizations differ by 5–50×.
129
138
-`b_alloc_pipeline` uses a paced source: per-message pace tokens and notification channels. The coordination overhead is included in the measured window.
0 commit comments