From 6366612250b90ae29bb39f0a6a908a8d6bca60cd Mon Sep 17 00:00:00 2001 From: Michael Netshipise Date: Sat, 20 Jun 2026 09:30:21 +0200 Subject: [PATCH] =?UTF-8?q?hll:=20hll=5Fmulti=5Fadd=20=E2=80=94=20batch=20?= =?UTF-8?q?many=20(name,items)=20into=20one=20RPC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors the new waymaker-server HllMultiAdd: one call writes several reserved HLLs (e.g. a presence flush across scope/bucket sketches), returning per-entry result codes. Vendored proto synced. Processed locally server-side for now (multi-name batch can't ring-route). Co-Authored-By: Claude Opus 4.8 --- proto/sketches.proto | 17 +++++++++++++++++ rust/src/probabilistic/hll.rs | 25 ++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/proto/sketches.proto b/proto/sketches.proto index 4cf70e1..b457174 100644 --- a/proto/sketches.proto +++ b/proto/sketches.proto @@ -36,6 +36,9 @@ service WaymakerSketchesService { // ----- HyperLogLog ----- rpc HllReserve (HllReserveRequest) returns (HllReserveResponse); rpc HllAdd (HllAddRequest) returns (HllAddResponse); + // Batch many (name, items) into ONE call (e.g. a presence flush). Processed + // locally today (can't ring-route a multi-name batch) — see the server TODO. + rpc HllMultiAdd (HllMultiAddRequest) returns (HllMultiAddResponse); rpc HllCount (HllCountRequest) returns (HllCountResponse); rpc HllMerge (HllMergeRequest) returns (HllMergeResponse); rpc HllDelete (HllDeleteRequest) returns (HllDeleteResponse); @@ -165,6 +168,20 @@ message HllAddResponse { string message = 3; } +message HllMultiAddEntry { + string name = 1; + repeated bytes items = 2; +} +message HllMultiAddRequest { + repeated HllMultiAddEntry entries = 1; +} +message HllMultiAddResponse { + bool success = 1; + string result_code = 2; + string message = 3; + repeated string entry_results = 4; +} + message HllCountRequest { string name = 1; } message HllCountResponse { bool success = 1; diff --git a/rust/src/probabilistic/hll.rs b/rust/src/probabilistic/hll.rs index 45cba6d..fbf0fd3 100644 --- a/rust/src/probabilistic/hll.rs +++ b/rust/src/probabilistic/hll.rs @@ -3,7 +3,8 @@ use crate::client::Client; use crate::error::{Error, Result}; use crate::sketches_server::{ - HllAddRequest, HllCountRequest, HllDeleteRequest, HllMergeRequest, HllReserveRequest, + HllAddRequest, HllCountRequest, HllDeleteRequest, HllMergeRequest, HllMultiAddEntry, + HllMultiAddRequest, HllReserveRequest, }; use tonic::Request; @@ -108,6 +109,28 @@ impl Client { Hll::new(self.clone(), name.into()) } + /// Batch many `(name, items)` HLL adds into ONE RPC — e.g. a presence flush that + /// writes the same id-set into several scope/bucket HLLs. Each name must already + /// be reserved (no auto-create); returns the per-entry result codes (`"ok"` / + /// `"no_such_hll"`, parallel to `entries`). NOTE: processed locally server-side + /// today (a multi-name batch can't ring-route) — single-node use only for now. + pub async fn hll_multi_add(&self, entries: Vec<(String, Vec>)>) -> Result> { + let mut c = self.sketches_client(); + let r = c + .hll_multi_add(Request::new(HllMultiAddRequest { + entries: entries + .into_iter() + .map(|(name, items)| HllMultiAddEntry { name, items }) + .collect(), + })) + .await? + .into_inner(); + if !r.success { + return Err(Error::server(r.result_code, r.message)); + } + Ok(r.entry_results) + } + pub async fn delete_hll(&self, name: impl Into) -> Result<()> { let mut c = self.sketches_client(); let r = c