Skip to main content

nodedb_types/sync/wire/
delta.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Delta push / ack / reject / collection-purged messages.
4
5use serde::{Deserialize, Serialize};
6
7use crate::sync::compensation::CompensationHint;
8use crate::sync::wire::ack_status::AckStatus;
9
10/// Delta push message (client → server, 0x10).
11#[derive(
12    Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
13)]
14pub struct DeltaPushMsg {
15    /// Collection the delta applies to.
16    pub collection: String,
17    /// Document ID.
18    pub document_id: String,
19    /// Loro CRDT delta bytes.
20    pub delta: Vec<u8>,
21    /// Client's peer ID (for CRDT identity).
22    pub peer_id: u64,
23    /// Per-mutation unique ID for dedup.
24    pub mutation_id: u64,
25    /// CRC32C checksum of `delta` bytes for integrity verification.
26    /// Computed by sender, validated by receiver. 0 for legacy clients.
27    #[serde(default)]
28    pub checksum: u32,
29    /// Device-assigned valid-time for the mutation (ms since Unix epoch).
30    ///
31    /// Populated by offline-capable clients so Origin can preserve the
32    /// application's notion of "when did this fact take effect" independently
33    /// of the Origin-assigned `system_from_ms`. `None` means the client did
34    /// not supply a valid-time — Origin will use `system_from_ms` as the
35    /// default valid-from.
36    #[serde(default)]
37    pub device_valid_time_ms: Option<i64>,
38    /// Stable identity of the originating producer (Lite peer ID or Origin node ID).
39    /// 0 for legacy / pre-idempotency clients.
40    #[serde(default)]
41    pub producer_id: u64,
42    /// Monotonic epoch counter incremented on every producer restart.
43    /// 0 for legacy / pre-idempotency clients.
44    #[serde(default)]
45    pub epoch: u64,
46    /// Per-stream monotonic sequence number within the epoch.
47    /// 0 for legacy / pre-idempotency clients.
48    #[serde(default)]
49    pub seq: u64,
50}
51
52/// Delta acknowledgment (server → client, 0x11).
53#[derive(
54    Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
55)]
56pub struct DeltaAckMsg {
57    /// Mutation ID being acknowledged.
58    pub mutation_id: u64,
59    /// Server-assigned LSN for this mutation.
60    pub lsn: u64,
61    /// Absolute clock-skew between `device_valid_time_ms` and the Origin
62    /// wall clock at commit, in milliseconds. `None` when the client did
63    /// not supply a device valid-time, or when skew was within tolerance
64    /// (≤ 24h). Populated so clients can surface a warning UX.
65    #[serde(default)]
66    pub clock_skew_warning_ms: Option<i64>,
67    /// Highest sequence number from this producer that has been durably applied.
68    /// 0 when the server has not yet recorded a sequence for this producer.
69    #[serde(default)]
70    pub applied_seq: u64,
71    /// Idempotency outcome of the acknowledged message.
72    #[serde(default)]
73    pub status: AckStatus,
74}
75
76/// Delta rejection (server → client, 0x12).
77#[derive(
78    Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
79)]
80pub struct DeltaRejectMsg {
81    /// Mutation ID being rejected.
82    pub mutation_id: u64,
83    /// Reason for rejection.
84    pub reason: String,
85    /// Compensation hints for the client.
86    pub compensation: Option<CompensationHint>,
87}
88
89/// Collection purged notification (server → client, 0x14).
90///
91/// Emitted when Origin hard-deletes a collection (retention window
92/// expired after `DROP COLLECTION` or explicit `DROP COLLECTION ... PURGE`).
93/// The receiving Lite client must:
94///
95/// 1. Drop all local Loro CRDT state for the collection.
96/// 2. Remove the collection's redb record.
97/// 3. Terminate any active shape subscriptions or streaming consumers
98///    sourced from the collection.
99/// 4. Fire the `on_collection_purged` client-trait callback.
100///
101/// `purge_lsn` is the Origin WAL LSN at which the hard-delete committed.
102/// Clients persist it so that on reconnect they can replay any purge
103/// events that landed while they were offline by querying
104/// `_system.dropped_collections` / purge event log at LSN > last_seen.
105#[derive(
106    Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
107)]
108pub struct CollectionPurgedMsg {
109    /// Numeric tenant ID the collection belonged to.
110    pub tenant_id: u64,
111    /// Collection name.
112    pub name: String,
113    /// Origin WAL LSN at which the hard-delete was committed.
114    pub purge_lsn: u64,
115}