Repository navigation
Server P11b-ii: a Live selection's references are pinned once, shared and written once (G29, D68) - #167
Conversation
… and written once (G29, D68) SnapshotContent.references is a SnapshotReferences: an Arc over the sorted records that serializes as the plain array. The engine pins one section per activation, every tick's snapshot shares it, and its canonical JSON is written and its cutoff-free checks run once. MarketSnapshot::new streams the canonical JSON into SHA-256, splicing the cached section bytes, so every id and stored snapshot is unchanged. Each snapshot still checks the section at its own cutoff.
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Reference section and validation crates/convex-ports/src/reference_master.rs, crates/convex-ports/src/snapshot.rs, crates/convex-ports/tests/snapshot_contracts.rs, crates/convex-ports/tests/support/snapshot_fixtures.rs |
SnapshotReferences stores resolved references and supports copy-on-write mutation, lookup, sorting, and validation. Reference resource checks use a shared scope check. Tests cover cutoff-specific validation and mutations. |
Canonical snapshot identity crates/convex-ports/Cargo.toml, crates/convex-ports/src/snapshot.rs, crates/convex-ports/tests/calibration_snapshots.rs, crates/convex-ports/tests/curve_recipe_snapshots.rs, crates/convex-ports/tests/snapshot_contracts.rs, crates/convex-ports/tests/support/snapshot_fixtures.rs |
Identity generation streams canonical content through a bounded digest and reuses cached reference JSON. Tests compare snapshot IDs with hashes of plain serialized content and check identity changes when content changes. |
Engine pinning and documentation crates/convex-engine/src/snapshot.rs, crates/convex-engine/tests/snapshots.rs, crates/convex-engine/tests/support/calibration_replay.rs, crates/convex-engine/RUNTIME.md, crates/convex-engine/SNAPSHOTS.md |
Engine snapshot construction and pinned inputs use SnapshotReferences. Tests use copy-on-write mutation. Documentation describes reference sharing and cutoff-dependent checks. |
Priority:
Estimated code review effort: 3 (Moderate) | ~25 minutes
Change: Refactor
Sequence Diagram(s)
sequenceDiagram
participant MarketSnapshot
participant SnapshotReferences
participant BoundedDigest
MarketSnapshot->>SnapshotReferences: Reuse canonical reference JSON
MarketSnapshot->>BoundedDigest: Stream canonical content
BoundedDigest-->>MarketSnapshot: Return schema-specific digest
Merge Risk: 
Minimal · up to 658cb
-
This change shares a Live selection's references across snapshots and streams the canonical JSON into the hash. Per the PR description, snapshot IDs, stored bytes and refusals stay the same, and the added tests check that identity matches plain serialization. No concrete merge-blocking risk was found.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passedFull details: Docstring Coverage
-
Explanation
Docstring coverage is 65.22% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 23 functions across 9 files. (3 skipped: 3 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches: 💡 1
-
📝 Generate docstrings: 💡
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
Summary
P11b-ii: a Live selection's references are one shared section, checked and written as JSON once per activation (G29, D68 A). The snapshot id is still SHA-256 over the same canonical bytes, so every id and every stored snapshot is unchanged.
Timers on
main(temporary, not committed) putMarketSnapshot::newat 1.62 ms of the 3.4 ms one-quote tick at 256 bonds:newserde_json::to_vecof the content (999 KB)The references are 70% of the bytes and were also cloned at every tick (0.15 ms in P11a).
Change
SnapshotContent.referencesis aSnapshotReferences: anArcover the sorted records.Deref<Target = [ResolvedBondReference]>andIntoIterator.make_mut()is the only way to change the records. It copies them when shared and drops the cached JSON and checks, so neither can go stale. There is noDerefMut.to_valueandjson!are unchanged and verification still refuses unsorted records.PartialEqandDebugread the records alone.PinnedInputs), and every tick's snapshot shares it instead of cloning 256 records.raw_valuefeature, enabled onconvex-ports; no new crate,Cargo.lockunchanged).MarketSnapshot::newstreams the canonical JSON into the hash through a mirror ofSnapshotContentthat writes the references from the cached JSON. The 16 MiB bound is counted as the bytes stream.validate_resolved_bond_at: the record was recorded byknown_at, and the terms and every resource are effective atas_ofand recorded byknown_at.validate_resolved_bondandvalidate_floating_resourcesshare the resource scope check with it, so the two cannot drift.normalizesorts the references only when they are out of order, so a shared section is never copied.RUNTIME.mdandSNAPSHOTS.mddescribe the shared section.Behaviour that changes
None. Ids, stored bytes, refusals and their errors are unchanged.
Tests
serde_json::to_vec(&content), the plain writer. The id is written by the mirror and the cached JSON, so a drift in the mirror's field order or skip rules fails these tests.make_mutfails both of these tests (checked by hand).curve-replay-schema-one.json,curve-replay-schema-two.json) still deserialize and verify.Numbers
Criterion medians,
--profile ci, WSL. Two interleaved rounds againstmain(d25000f), swapping in itsconvex-engineandconvex-portssources and test support:mainlive_throughput/burst1/256(one-quote tick)live_throughput/burst512/256snapshot/verifysnapshot_assemble/256(Captured/Replayresolve)snapshot/value_uncachedsnapshot/value_builtlive_ticknew's 1.62 ms and the 0.15 ms clone, less the 0.40 ms hash and the per-snapshot checks that stay.snapshot/verifycallsverify()again and again on one snapshot, whose section already holds its JSON and its cutoff-free checks from when it was made. So it times the cutoff checks and the streamed hash.verifyhas been off the Live path since P11b-i.value_uncachedis 4–6 µs (5%) slower in both rounds, and four more runs of this branch gave 87.9–89.4 µs. Nothing on that path uses the section beyond the binary-search lookupmainalso does, now one pointer further away. The cause is not found.live_tickstamps rawUtc::now(), so a WSL clock step stops it (P11d).Not done here (next P11b step)
changedbuilding 256 contexts (0.34 ms).Verification
WSL,
--locked:cargo fmt --check;cargo clippy --all-targets -- -D warningsforconvex-ports,convex-engine,convex-server,convex-ext-redb,convex-ext-file;RUSTDOCFLAGS=-Dwarnings cargo doc --no-deps --all-featuresforconvex-portsandconvex-engine.cargo test -p convex-ports: 43 passed.cargo test -p convex-engine: 207 passed, 1 ignored, as onmain.cargo test -p convex-ext-redb -p convex-ext-file -p convex-server -- --test-threads=1: 353 passed.tools/assurance/check.py, alone and with--base d25000f5: passed.Summary by CodeRabbit