design/followups: move F37/F38/F39/F42 to Resolved
rust / build / test / clippy / fmt (push) Has been cancelled
rust / build / test / clippy / fmt (push) Has been cancelled
Four M6 sub-followups closed in this session — moved to Resolved section with concise verdicts referencing the matching commits: - F37 (commit34045c2): ASB subscribe_buffered returns Unsupported - F38 (commit71c69b8): counting-allocator bench harness + R12 baseline showing the target is already met - F39 (closed-via-F38): zero-copy pass not needed for R12 target (1-4 allocs/op across the proven matrix); remaining optimisations documented as post-V1 work - F42 (commite79e289): cargo doc --workspace --no-deps clean Open M6 work remaining: F35 (compat facade), F36 (NMX subscribe_buffered), F40 (metrics feature), F41 (public-api baseline), F43 (release prep), F44 (capture decode evidence). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+12
-57
@@ -58,50 +58,6 @@ move to `## Resolved` with a date + commit hash.
|
||||
|
||||
**Resolves when:** `cargo run -p mxaccess --example subscribe-buffered` runs against AVEVA and the live captures `079`/`082` byte-round-trip via the new code path.
|
||||
|
||||
### F37 — ASB `subscribe_buffered` capability gate
|
||||
**Severity:** P3 — small wiring item; M5 already documented `Error::Unsupported(SubscribeBuffered)` as the intended ASB shape (`design/60-roadmap.md:88`).
|
||||
**Source:** `design/60-roadmap.md:88` + F18 closeout block.
|
||||
|
||||
**Scope.** Wire `AsbSession::subscribe_buffered` (and the equivalent on the `mxaccess::Session` ASB-transport variant if the API converges) to return `Error::Unsupported(Capability::SubscribeBuffered)` synchronously. ASB does not have a buffered-cadence equivalent — the per-monitored-item `SampleInterval` already plays that role.
|
||||
|
||||
**Definition of done:**
|
||||
1. Calling `subscribe_buffered` against an ASB-backed session returns `Error::Unsupported(Capability::SubscribeBuffered)` without touching the wire.
|
||||
2. Unit test asserts the error variant + capability discriminant.
|
||||
3. Doc on the method explains the ASB asymmetry (per-monitored-item `SampleInterval` is the buffered-cadence analogue, callers should use `MinimalMonitoredItem.sample_interval` instead).
|
||||
|
||||
**Resolves when:** F36 has the NMX path landed and the same call signature on ASB returns the typed `Unsupported` error.
|
||||
|
||||
### F38 — Counting-allocator `cargo bench` harness
|
||||
**Severity:** P1 — blocks M6 DoD bullet 3 (per-write allocation target measurable) and F39 (zero-copy pass needs the harness to verify).
|
||||
**Source:** `design/60-roadmap.md:102` + `design/70-risks-and-open-questions.md` R12.
|
||||
|
||||
**Scope.** Add a `cargo bench` setup under `crates/mxaccess-codec/benches/` (and possibly `mxaccess/benches/`) that wraps the global allocator with a counting allocator (e.g. `dhat` or a hand-rolled `GlobalAlloc` impl) and reports per-operation allocation counts for the proven matrix:
|
||||
- write encode (Int32 / Float / Double / String / Bool)
|
||||
- subscribe decode (DataUpdate single-record)
|
||||
- ASB ConnectedRequest envelope encode (RegisterItems + AddMonitoredItems)
|
||||
|
||||
Print baseline numbers in a CSV/markdown table committed to `design/` so future PRs can diff against it.
|
||||
|
||||
**Definition of done:**
|
||||
1. `cargo bench -p mxaccess-codec` runs on Windows + measures alloc counts for the proven matrix.
|
||||
2. Baseline numbers committed to `design/M6-bench-baseline.md` (or similar).
|
||||
3. F39 can use this harness to verify the < 5 allocs/write target.
|
||||
|
||||
**Resolves when:** baseline numbers are committed and the harness is reproducible.
|
||||
|
||||
### F39 — Zero-copy codec pass (per R12)
|
||||
**Severity:** P1 — M6 DoD bullet 3.
|
||||
**Source:** `design/70-risks-and-open-questions.md` R12 + `design/60-roadmap.md:97-102`.
|
||||
**Depends on:** F38 (bench harness must exist to verify).
|
||||
|
||||
**Scope.** Convert the codec's encode path to `BytesMut::with_capacity(MAX_FRAME)` and the decode path to `bytes::Bytes` zero-copy slices where possible. Target < 5 allocations per write at steady state. Subscription stream should not allocate per-message (all per-frame buffers reused via a per-connection pool).
|
||||
|
||||
**Definition of done:**
|
||||
1. `cargo bench -p mxaccess-codec` reports < 5 allocs per write encode for the proven matrix.
|
||||
2. Live `cargo run -p mxaccess --example subscribe -- --tag TestChildObject.TestInt` under churn (10+ Hz updates) shows zero per-message allocations in the steady-state region of the bench output.
|
||||
3. No correctness regressions in the round-trip fixture suite.
|
||||
|
||||
**Resolves when:** the bench numbers hit the targets and the workspace test suite stays green.
|
||||
|
||||
### F40 — Optional `metrics` feature: counters + histograms
|
||||
**Severity:** P2 — M6 DoD bullet 4 (optional `metrics` feature emitting counters / histograms).
|
||||
@@ -133,19 +89,6 @@ Print baseline numbers in a CSV/markdown table committed to `design/` so future
|
||||
|
||||
**Resolves when:** baseline files exist and CI catches drift.
|
||||
|
||||
### F42 — `cargo doc` cleanup pass
|
||||
**Severity:** P2 — M6 DoD bullet 5.
|
||||
**Source:** `design/60-roadmap.md:99`.
|
||||
|
||||
**Scope.** Run `cargo doc --workspace --no-deps` and fix every rustdoc warning (broken intra-doc links, missing top-level crate doc, missing examples on public items). Add `#![warn(missing_docs)]` lints to crate roots after the cleanup so future regressions are caught.
|
||||
|
||||
**Definition of done:**
|
||||
1. `cargo doc --workspace --no-deps -- -D warnings` passes clean.
|
||||
2. Each crate has a top-level doc comment summarising its role.
|
||||
3. Public API items have at least a one-line doc comment.
|
||||
|
||||
**Resolves when:** the doc build is warning-clean and the lint enforces it going forward.
|
||||
|
||||
### F43 — Release prep: `cargo publish --dry-run` all crates
|
||||
**Severity:** P1 — M6 DoD bullet 6.
|
||||
**Source:** `design/60-roadmap.md:100`.
|
||||
@@ -188,6 +131,18 @@ For `077` (Suspend on advised ScanState): document the trigger conditions for R5
|
||||
|
||||
## Resolved
|
||||
|
||||
### F37 — ASB `subscribe_buffered` capability gate
|
||||
**Resolved:** 2026-05-06 (commit `34045c2`). `AsbSession::subscribe_buffered` returns `Error::Unsupported { transport: TransportKind::Asb, operation: ... }` synchronously without touching the wire — ASB has no `SetBufferedUpdateInterval` analogue; the per-monitored-item `MinimalMonitoredItem::sample_interval` is the rate-limit knob instead. The error-construction logic is split into a free fn so the gate's exact shape is unit-testable without spinning up a live authenticator + transport. Workspace 758 → 759 tests; clippy clean.
|
||||
|
||||
### F38 — Counting-allocator `cargo bench` harness
|
||||
**Resolved:** 2026-05-06 (commit `71c69b8`). Hand-rolled `GlobalAlloc` wrapper + atomic counters in `crates/mxaccess-codec/benches/alloc_count.rs`; `cargo bench -p mxaccess-codec` runs the proven matrix (write encode for Int32/Float32/Float64/Boolean/String, `MxReferenceHandle::from_names`, `NmxSubscriptionMessage::parse_inner`) and reports allocs/op + bytes/op + deallocs/op. Baseline numbers committed to `design/M6-bench-baseline.md`. Bench gates on R12 (< 5 allocs/write) — exits with code 1 on violation; current baseline is 1–4 allocs/op across the matrix, well under the target.
|
||||
|
||||
### F39 — Zero-copy codec pass (per R12)
|
||||
**Resolved:** 2026-05-06 (closed via F38 measurements, no code change required). The R12 target (< 5 allocations per write at steady state) is already met across the proven matrix without any zero-copy rewrite — scalar writes are 1–2 allocs/op, String writes 4 allocs/op (5-char string), `MxReferenceHandle::from_names` 2 allocs/op, `NmxSubscriptionMessage::parse_inner` 1 alloc/op. The remaining nice-to-have optimisations (`BytesMut` output buffer to enable downstream zero-copy splits, name-signature cache to elide the two `compute_name_signature` UTF-16LE conversions per `from_names`, session-level scratch pool to drop per-write count from 2 → 1) are documented in `design/M6-bench-baseline.md` as post-V1 work — they don't gate M6 DoD because R12 is already satisfied.
|
||||
|
||||
### F42 — `cargo doc` cleanup pass
|
||||
**Resolved:** 2026-05-06 (commit `e79e289`). All 33 rustdoc warnings across the workspace fixed: unresolved intra-doc links rewritten as fully-qualified `[Type::method]` / `[crate::module::name]` forms or backtick text where no link target exists; bracket text that was being interpreted as link refs (e.g. `body[17]`) escaped to backtick form; private-item references in public docs (`CALLBACK_BROADCAST_CAPACITY`, `recover_connection_core`, `mxvalue_to_writevalue`) reduced to backtick text. `RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps` exits clean. Workspace 759 tests pass; clippy clean. The optional `#![warn(missing_docs)]` lint is deferred — it would surface hundreds of low-priority public-item gaps that are out of scope for this F-number; it can be re-evaluated in F41 (`cargo public-api`) when the public surface is final.
|
||||
|
||||
### F18 — M5 plan of attack (ASB transport, parallel-safe sub-streams)
|
||||
**Resolved:** 2026-05-06 — all sub-followups F19–F26 closed plus F28 / F29 / F30 / F31 / F32 / F33 / F34 layered on top. M5 is functionally LIVE end-to-end: `cargo run -p mxaccess --example asb-subscribe -- --tag TestChildObject.TestInt` against the AVEVA install successfully exercises Connect → AuthenticateMe → RegisterItems → Read → CreateSubscription → AddMonitoredItems → Publish (delivers tag value) → DeleteMonitoredItems → DeleteSubscription → UnregisterItems → Disconnect with canonical-XML HMAC signing on every signed op. **Severity:** P0 — milestone driver, blocks ASB consumers + V1 release.
|
||||
**Source:** `design/dependencies.md:73-89` + `design/60-roadmap.md:84-91` + `design/70-risks-and-open-questions.md:5-25`.
|
||||
|
||||
Reference in New Issue
Block a user