nodedb_types/sync/wire/columnar.rs
1// SPDX-License-Identifier: Apache-2.0
2
3//! Columnar insert sync messages (client → server / server → client).
4//!
5//! `ColumnarInsertMsg` carries a batch of typed row values from a Lite
6//! client to Origin. Each row is a MessagePack-serialized `Vec<Value>` in
7//! schema column order, matching the collection's `ColumnarSchema`.
8//!
9//! Wire layout mirrors `TimeseriesPushMsg`: typed payload + schema hint +
10//! a monotonic `batch_id` for dedup / ACK correlation.
11
12use serde::{Deserialize, Serialize};
13
14use crate::sync::wire::ack_status::AckStatus;
15
16/// Columnar batch insert (client → server, 0xA0).
17///
18/// Carries one or more rows for a columnar collection. Each entry in
19/// `rows` is a MessagePack-serialized `Vec<nodedb_types::value::Value>`
20/// with entries in schema column order.
21///
22/// `schema_bytes` is a MessagePack-serialized `ColumnarSchema`. Origin uses
23/// it to create the collection if it does not yet exist (definition-sync
24/// guarantees it will already exist in most cases, but the schema hint
25/// lets Origin validate column count and types rather than guessing).
26#[derive(
27 Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
28)]
29pub struct ColumnarInsertMsg {
30 /// Lite instance ID (for routing and dedup).
31 pub lite_id: String,
32 /// Target collection name.
33 pub collection: String,
34 /// Batch of rows. Each element is MessagePack `Vec<Value>` (schema column order).
35 pub rows: Vec<Vec<u8>>,
36 /// Monotonic batch ID (Lite-assigned, per-collection). Used for ACK correlation.
37 pub batch_id: u64,
38 /// MessagePack-serialized `ColumnarSchema`. May be empty for collections
39 /// that were already synced via definition-sync.
40 #[serde(default)]
41 pub schema_bytes: Vec<u8>,
42 /// Stable identity of the originating producer. 0 for legacy clients.
43 #[serde(default)]
44 pub producer_id: u64,
45 /// Monotonic epoch counter incremented on every producer restart.
46 #[serde(default)]
47 pub epoch: u64,
48 /// Per-stream monotonic sequence number within the epoch.
49 #[serde(default)]
50 pub seq: u64,
51}
52
53/// Columnar insert acknowledgment (server → client, 0xA1).
54#[derive(
55 Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
56)]
57pub struct ColumnarInsertAckMsg {
58 /// Collection acknowledged.
59 pub collection: String,
60 /// Batch ID from the originating `ColumnarInsertMsg`.
61 pub batch_id: u64,
62 /// Number of rows successfully inserted.
63 pub accepted: u64,
64 /// Number of rows rejected (schema mismatch, constraint violation, etc.).
65 pub rejected: u64,
66 /// Optional rejection detail for the first rejected row.
67 #[serde(default)]
68 pub reject_reason: Option<String>,
69 /// Highest sequence number from this producer that has been durably applied.
70 #[serde(default)]
71 pub applied_seq: u64,
72 /// Idempotency outcome of the acknowledged message.
73 #[serde(default)]
74 pub status: AckStatus,
75}