Skip to content

feat(monitor): dynamic coordinator→edge sampling coupling (edge half) - #481

Merged
zzylol merged 1 commit into
mainfrom
feat/coordinator-sampling-coupling
Jun 11, 2026
Merged

zzylol merged 1 commit into
mainfrom
feat/coordinator-sampling-coupling

Conversation

@zzylol

@zzylol zzylol commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Edge half of the dynamic coordinator↔sampling coupling

Completes the distributed-NitroSketch loop that #480 teed up (the Grant.SampleP hook + AllocateSampleRates + the design doc): the edge now reports its observed per-window rate so the coordinator can allocate per-edge update-sampling probabilities, and applies the coordinator-granted sample_p to its sampling-capable wrappers at the next epoch boundary.

Proto (both new fields, regenerated bindings)

  • SlackGrant.sample_p (field 6) — coord→edge.
  • MonitorReport.rate (field 8) — edge→coord.

Edge wiring

  • Report rate: monitorState.obsCount (per-epoch), stamped into Report.Rate.
  • Receive grant: OnGrant stores grant.SampleP; persists across EpochReset (allocation holds until re-granted), cleared by ForceReregister.
  • Apply at the boundary (never mid-window): tumbling rotation drains the series map; the granted p is stamped onto each brand-new empty wrapper at birth (window.go admitSeriesLockedmonitorSampleHook), so one p governs the whole next window and every merge operand.
  • Family gate: only CMS / Count-Sketch / DDSketch (by SketchType, then a SampleSetter interface assert); Sum/KLL/HLL are a true no-op (HLL deliberately doesn't implement it — max-based, no CPU win + biased).

Tests

OnGrant store/clear, report carries rate, sample_p survives EpochReset, full apply path (Count-Sketch new-window wrapper picks up p while the in-flight wrapper stays 1.0; Sum no-op), and cross-language wire fixtures (Go-encoded sample_p/rate decode in Rust; a Rust-encoded grant decodes here). Build + ./monitor/ . ./sketches/ + nested grpcclient module green.

Pairs with the coordinator half in ASAPQuery-backend (computes p_i via allocate_sample_rates + the ε-floor and populates SlackGrant.sample_p). Coupling validated end-to-end across the wire, both directions.

🤖 Generated with Claude Code

Wires the edge side of the distributed-NitroSketch dynamic coupling: the edge
reports its observed per-window rate so the coordinator can allocate per-edge
update-sampling probabilities, and applies the coordinator-granted sample_p to
its sampling-capable sketch wrappers at the next epoch boundary.

Proto (monitor.proto + regenerated bindings): SlackGrant.sample_p (field 6,
coord→edge) + MonitorReport.rate (field 8, edge→coord).

- types.go: Report.Rate (observed items/window).
- grpcclient/client.go: map outbound Report.Rate → proto rate; inbound proto
  SlackGrant.sample_p → monitor.Grant.SampleP.
- engine.go: monitorState tracks obsCount (per-epoch rate) + grantedSampleP;
  Observe increments obsCount; sendReportLocked stamps Rate; OnGrant stores
  grant.SampleP; grantedSampleP survives EpochReset (allocation persists until
  re-granted) but is cleared by ForceReregister (restarted coordinator). New
  GrantedSampleP(aggID) accessor (defaults 1.0).
- Apply at epoch boundary (never mid-window): tumbling rotation drains the
  series map and next-window sketches are created lazily on first observe, so
  the granted p is stamped onto each brand-new empty wrapper at birth via a new
  monitorSampleHook (window.go admitSeriesLocked). The in-flight window keeps
  its existing p; one p governs the whole next window and every merge operand.
- Family gate (two layers, no panic, no import cycle): precompute
  applyGrantedSampleP installs the hook ONLY for CMS/CountSketch/DDSketch by
  SketchType; the hook asserts a new SampleSetter{SetSampleP(float64)} interface
  (added to CMS/CountSketch/DDSketch wrappers, delegating to WithSampleP) and is
  a true no-op for Sum/KLL/HLL (HLL deliberately does NOT implement it — its
  max-based estimator gains no CPU from update-sampling and would bias).

Tests: OnGrant stores/clears sample_p; report carries rate; sample_p survives
EpochReset; full apply path (Count-Sketch new-window wrapper → granted p while
in-flight wrapper stays 1.0; Sum no-op); cross-language wire fixtures
(Go-encoded SlackGrant.sample_p / MonitorReport.rate, and a Rust-encoded grant
decoded here) — the gate the Rust side (coupling_wire_compat.rs) mirrors.

Pairs with the coordinator half in ASAPQuery-backend. See
docs/distributed-nitrosketch-coordinated-sampling.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@zzylol
zzylol merged commit 93edda7 into main Jun 11, 2026
@zzylol
zzylol deleted the feat/coordinator-sampling-coupling branch June 11, 2026 18:42
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.

1 participant