Skip to content

chore: release v0.3.2#4

Merged
polaz merged 1 commit into
mainfrom
release-plz-2026-04-12T08-14-38Z
Apr 12, 2026
Merged

chore: release v0.3.2#4
polaz merged 1 commit into
mainfrom
release-plz-2026-04-12T08-14-38Z

Conversation

@sw-release-bot
Copy link
Copy Markdown
Contributor

🤖 New release

  • coordinode-core: 0.3.1 -> 0.3.2
  • coordinode-storage: 0.3.1 -> 0.3.2
  • coordinode-search: 0.3.1 -> 0.3.2
  • coordinode-vector: 0.3.1 -> 0.3.2
  • coordinode-query: 0.3.1 -> 0.3.2
  • coordinode-raft: 0.3.1 -> 0.3.2
  • coordinode-embed: 0.3.1 -> 0.3.2
  • coordinode-auth: 0.3.1 -> 0.3.2
  • coordinode-server: 0.3.1 -> 0.3.2
  • coordinode-s3: 0.3.1 -> 0.3.2
Changelog

coordinode-server

0.3.1 - 2026-04-11

Added

  • (query) HNSW-accelerated vector top-K via planner optimization

Testing

  • (server) add cross-service regression test for create_node persistence


This PR was generated with release-plz.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@polaz polaz merged commit 8717378 into main Apr 12, 2026
6 of 7 checks passed
polaz added a commit that referenced this pull request May 21, 2026
…imitives

Closes the trigger surface for G103 sub-system #4 (background
overflow compactor). After this slice the catalog can: (a)
discover every bucket with stale overflow, and (b) compact all
of them in one driver tick.

New modality API on `TimeSeriesStore`:
- `list_overflow_buckets() -> Vec<(u32, NodeId)>` — single prefix
  scan over `ts_overflow:` folded to unique `(label_id, bucket_id)`
  pairs. Memory bounded by the number of stale buckets, not the
  overflow volume. Malformed overflow keys (< 12-byte suffix) skip
  with `tracing::warn!` instead of erroring.

New catalog API on `BucketCatalog`:
- `compact_all_pending() -> CatalogResult<usize>` — discover via
  `list_overflow_buckets`, run `compact_if_needed` against each
  candidate, return count of buckets that actually compacted
  (i.e. were above `OVERFLOW_COMPACT_THRESHOLD`). Production
  wires this into a periodic `tokio::time::interval` task per
  shard above the catalog — the catalog itself spawns no threads.

4 new tests:
- `list_overflow_buckets_returns_unique_pairs_across_multiple_entries`
  — 4 overflow entries across 3 unique `(label, bucket)` pairs;
  list returns exactly 3 in sorted order. Same `bucket_id` under
  different labels stays distinct (the pair, not the bucket_id
  alone, identifies a target).
- `list_overflow_buckets_empty_when_no_overflow` — empty path.
- `compact_all_pending_discovers_and_compacts_every_stale_bucket`
  — 3 buckets: A and B with 51 overflow each (above threshold),
  C with 10 (below). Driver compacts A and B (returns 2), leaves
  C's overflow intact.
- `compact_all_pending_no_op_when_overflow_set_empty` — empty
  baseline returns 0.

Sub-system #4 status update in lib.rs comments (next commit on
GAPS.md will mirror): the trigger primitive landed in Slice C; the
discover-and-compact primitive lands here. Remaining for the full
sub-system: spawning the periodic driver above the catalog (the
catalog deliberately spawns no threads — driver lives in a service
layer; out of scope for this crate).

Verified: cargo clippy --workspace --all-targets clean
(-D warnings), 183/183 modality + timeseries tests pass.
polaz added a commit that referenced this pull request May 21, 2026
…with engine-backed restart monotonicity

User pointed out: lsm-tree IS the durable layer. The prior commit
(03f182c) documented restart-monotonicity as a follow-up needing
"a persistence layer"; that layer was already on hand via the
StorageEngine. This commit closes the gap end-to-end.

## New: PersistentMonotonicHlcClock

Wraps the same CAS-monotonic logic as MonotonicHlcClock but adds:

- **Engine-backed checkpoint** under `Partition::Schema` key
  `schema:meta:ts_clock:<shard_id_u16_be>` (8-byte big-endian i64).
- **Seed-on-load** from `max(persisted_last + 1, wall_clock_now)`.
  First stamp after open is strictly > both the persisted value
  AND the current wall clock, so a backward NTP jump can't violate
  monotonicity.
- **Periodic persistence** every 64 calls to `next()` on the hot
  path. Best-effort: a transient engine error logs `tracing::warn`
  and the next checkpoint catches up. Worst-case data loss on
  crash is ≤63 stamps; combined with the seed-on-load rule, the
  only failure mode is a backward wall-clock jump that exceeds
  the lost-stamp window.
- **Explicit `checkpoint()`** for the catalog flush path — forces
  a write regardless of cadence so crash recovery sees a stamp
  strictly bounding every flushed measurement.

## New: MonotonicHlcClock public surface

- `with_prior(prior: i64)` — explicit seed (used by
  PersistentMonotonicHlcClock and future Raft-leader-stamped
  variants to resume from a replicated last stamp).
- `current() -> i64` — read last-issued stamp without burning a
  number on the read (checkpoint reads, observability hooks).

## Free functions (also publicly exported)

- `load_last_stamp(engine, shard_id) -> Result<Option<i64>>` —
  reads the checkpoint key; `None` for first-ever open; tolerates
  corrupt body (8-byte length check) by returning `None` with a
  warning (not an error — a corrupt checkpoint falls back to wall
  clock, which is safe).
- `persist_last_stamp(engine, shard_id, stamp) -> Result<()>` —
  overwrites the checkpoint key with 8-byte BE stamp.

## Storage key choice

`Partition::Schema` with reserved key
`schema:meta:ts_clock:<shard_id_u16_be>` — mirrors the convention
used by `schema:current_revision:<kind>:<name>` etc. (engine-
reserved metadata keys live under the schema partition).

## Tests (5 new in clock::tests)

- `persistent_clock_seeds_from_wall_when_no_checkpoint` — first
  open, no persisted value, first stamp ≥ wall clock at open
  time, strict monotonic from there.
- `persistent_clock_resumes_above_persisted_on_reopen` — burn 64
  stamps, force checkpoint, drop clock, reopen. First stamp from
  the new instance must be strictly > the persisted value
  regardless of wall clock state (simulates the backward NTP
  jump).
- `persistent_clock_explicit_checkpoint_writes_current_stamp` —
  explicit `checkpoint()` after a single `next()` persists exactly
  that stamp.
- `persistent_clock_shards_dont_interfere` — two shards on the
  same engine persist to disjoint keys; writes on shard 1 leave
  shard 2's checkpoint absent.
- `persistent_clock_corrupt_checkpoint_falls_back_to_wall_clock`
  — plant garbage at the checkpoint key, `load_last_stamp` returns
  `None` (with warn), clock opens normally seeded from wall.

## Updated documentation

- `MonotonicHlcClock` docstring no longer claims persistence is a
  "follow-up" — it now points readers to PersistentMonotonicHlcClock
  for production use and explains when the bare variant is
  appropriate (tests, future Raft-stamped variants).

## Verified

- `cargo clippy --workspace --all-targets -- -D warnings` clean.
- `cargo nextest run -p coordinode-timeseries` 49/49 pass (5 new
  persistence tests + prior 44).

## Out of scope (genuinely separate work)

- **Catalog wiring**: BucketCatalog construction sites in
  production code (not yet wired — the v0.4-alpha gate work
  that hooks catalog into coordinode-query/server is where the
  PersistentMonotonicHlcClock will replace MonotonicHlcClock).
- **Raft-leader-stamped variant** for multi-replica CE: needs
  consensus log integration; will land alongside the Raft-aware
  bucket reopen path.
@sw-release-bot sw-release-bot Bot mentioned this pull request May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants