1#[cfg(not(target_arch = "wasm32"))]
7use crate::storage::engine::StorageEngine;
8
9#[cfg(not(target_arch = "wasm32"))]
10use super::super::core::NodeDbLite;
11
12#[cfg(not(target_arch = "wasm32"))]
13#[async_trait::async_trait]
14impl<S: StorageEngine> crate::sync::SyncDelegate for NodeDbLite<S> {
15 fn sync_identity(&self) -> crate::identity::LiteIdentity {
16 NodeDbLite::sync_identity(self)
17 }
18
19 async fn regenerate_identity(&self) {
20 if let Err(e) = NodeDbLite::regenerate_identity(self).await {
21 tracing::error!(
26 error = %e,
27 "SyncDelegate: fork recovery failed — this replica cannot sync until its \
28 producer identity is replaced"
29 );
30 }
31 }
32
33 async fn rotate_peer_id(&self) {
34 if let Err(e) = NodeDbLite::rotate_peer_id(self).await {
35 tracing::error!(
36 error = %e,
37 "SyncDelegate: peer-id rotation failed — this replica cannot sync until its \
38 Loro peer id is replaced"
39 );
40 }
41 }
42
43 fn pending_deltas(&self) -> Vec<crate::engine::crdt::engine::PendingDelta> {
44 self.pending_crdt_deltas().unwrap_or_default()
45 }
46
47 async fn set_pending_delta_seq(&self, mutation_id: u64, seq: u64) {
48 if let Err(e) = self.set_crdt_pending_delta_seq(mutation_id, seq) {
49 tracing::warn!(
50 mutation_id,
51 seq,
52 error = %e,
53 "SyncDelegate: set_pending_delta_seq failed"
54 );
55 }
56 }
57
58 fn acknowledge(&self, mutation_id: u64) {
59 if let Err(e) = self.acknowledge_deltas(mutation_id) {
60 tracing::warn!(mutation_id, error = %e, "SyncDelegate: acknowledge failed");
61 }
62 }
63
64 fn reject(&self, mutation_id: u64) {
65 if let Err(e) = self.reject_delta(mutation_id) {
66 tracing::warn!(mutation_id, error = %e, "SyncDelegate: reject failed");
67 }
68 }
69
70 fn reject_with_policy(
71 &self,
72 mutation_id: u64,
73 hint: &nodedb_types::sync::compensation::CompensationHint,
74 ) {
75 if let Err(error) = super::reject::handle_reject_with_policy_impl(self, mutation_id, hint) {
76 tracing::error!(mutation_id, %error, "delta rejection maintenance returned an error");
77 }
78 }
79
80 fn import_remote(&self, collection: &str, data: &[u8]) {
81 if let Err(e) = self.import_remote_deltas(collection, data) {
82 tracing::warn!(
83 collection = %collection,
84 error = %e,
85 "SyncDelegate: import_remote failed"
86 );
87 }
88 }
89
90 async fn apply_remote_row(
91 &self,
92 msg: &nodedb_types::sync::wire::RowPushMsg,
93 ) -> Result<(), nodedb_types::error::NodeDbError> {
94 let delete = matches!(msg.op, nodedb_types::sync::wire::RowOp::Delete);
95 self.apply_remote_row(&msg.collection, &msg.document_id, &msg.payload, delete)
96 .await
97 }
98
99 async fn handle_array_delta(
100 &self,
101 msg: &nodedb_types::sync::wire::ArrayDeltaMsg,
102 ) -> Option<nodedb_types::sync::wire::ArrayAckMsg> {
103 super::array::handle_array_delta_impl(self, msg).await
104 }
105
106 async fn handle_array_delta_batch(
107 &self,
108 msg: &nodedb_types::sync::wire::ArrayDeltaBatchMsg,
109 ) -> Option<nodedb_types::sync::wire::ArrayAckMsg> {
110 super::array::handle_array_delta_batch_impl(self, msg).await
111 }
112
113 async fn handle_array_reject(
114 &self,
115 msg: &nodedb_types::sync::wire::ArrayRejectMsg,
116 ) -> Option<nodedb_types::sync::wire::ArrayCatchupRequestMsg> {
117 super::array::handle_array_reject_impl(self, msg).await
118 }
119
120 async fn handle_array_snapshot(&self, msg: &nodedb_types::sync::wire::ArraySnapshotMsg) {
121 super::array::handle_array_snapshot_impl(self, msg).await
122 }
123
124 async fn handle_array_snapshot_chunk(
125 &self,
126 msg: &nodedb_types::sync::wire::ArraySnapshotChunkMsg,
127 ) -> Option<nodedb_types::sync::wire::ArrayAckMsg> {
128 super::array::handle_array_snapshot_chunk_impl(self, msg).await
129 }
130
131 fn begin_array_catchup(&self) -> Vec<nodedb_types::sync::wire::ArrayCatchupRequestMsg> {
132 super::array::begin_array_catchup_impl(self)
133 }
134
135 async fn pending_array_ops(
136 &self,
137 after: Option<nodedb_array::sync::hlc::Hlc>,
138 limit: usize,
139 ) -> Result<Vec<crate::sync::array::PendingArrayOp>, crate::error::LiteError> {
140 super::array::pending_array_ops_impl(self, after, limit).await
141 }
142
143 async fn persist_array_op_seq(
144 &self,
145 op: &crate::sync::array::PendingArrayOp,
146 ) -> Result<(), crate::error::LiteError> {
147 super::array::persist_array_op_seq_impl(self, op).await
148 }
149
150 async fn retire_array_ops(
151 &self,
152 hlcs: &[nodedb_array::sync::hlc::Hlc],
153 ) -> Result<(), crate::error::LiteError> {
154 super::array::retire_array_ops_impl(self, hlcs).await
155 }
156
157 fn array_schema_announce(
158 &self,
159 array: &str,
160 ) -> Result<Option<nodedb_types::sync::wire::ArraySchemaSyncMsg>, crate::error::LiteError> {
161 super::array::array_schema_announce_impl(self, array)
162 }
163
164 async fn pending_columnar_batches(
165 &self,
166 ) -> Vec<(
167 Vec<u8>,
168 crate::sync::outbound::columnar::PendingColumnarBatch,
169 )> {
170 super::columnar_handlers::pending_columnar_batches_impl(self).await
171 }
172
173 async fn mark_columnar_batch_in_flight(&self, batch_id: u64, durable_key: Vec<u8>) {
174 super::columnar_handlers::mark_columnar_batch_in_flight_impl(self, batch_id, durable_key)
175 .await
176 }
177
178 async fn ack_columnar_batch_in_flight(&self, batch_id: u64) {
179 super::columnar_handlers::ack_columnar_batch_in_flight_impl(self, batch_id).await
180 }
181
182 async fn acknowledge_columnar_batch(&self, durable_key: Vec<u8>) {
183 super::columnar_handlers::acknowledge_columnar_batch_impl(self, durable_key).await
184 }
185
186 async fn pending_vector_inserts(
187 &self,
188 ) -> Vec<(Vec<u8>, crate::sync::outbound::vector::PendingVectorInsert)> {
189 super::vector_handlers::pending_vector_inserts_impl(self).await
190 }
191
192 async fn mark_vector_insert_in_flight(&self, batch_id: u64, durable_key: Vec<u8>) {
193 super::vector_handlers::mark_vector_insert_in_flight_impl(self, batch_id, durable_key).await
194 }
195
196 async fn ack_vector_insert_in_flight(&self, batch_id: u64) {
197 super::vector_handlers::ack_vector_insert_in_flight_impl(self, batch_id).await
198 }
199
200 async fn acknowledge_vector_insert(&self, durable_key: Vec<u8>) {
201 super::vector_handlers::acknowledge_vector_insert_impl(self, durable_key).await
202 }
203
204 async fn pending_vector_deletes(
205 &self,
206 ) -> Vec<(Vec<u8>, crate::sync::outbound::vector::PendingVectorDelete)> {
207 super::vector_handlers::pending_vector_deletes_impl(self).await
208 }
209
210 async fn mark_vector_delete_in_flight(&self, batch_id: u64, durable_key: Vec<u8>) {
211 super::vector_handlers::mark_vector_delete_in_flight_impl(self, batch_id, durable_key).await
212 }
213
214 async fn ack_vector_delete_in_flight(&self, batch_id: u64) {
215 super::vector_handlers::ack_vector_delete_in_flight_impl(self, batch_id).await
216 }
217
218 async fn acknowledge_vector_delete(&self, durable_key: Vec<u8>) {
219 super::vector_handlers::acknowledge_vector_delete_impl(self, durable_key).await
220 }
221
222 async fn pending_fts_indexes(
223 &self,
224 ) -> Result<Vec<(Vec<u8>, crate::sync::outbound::fts::PendingFtsIndex)>, crate::error::LiteError>
225 {
226 super::fts_handlers::pending_fts_indexes_impl(self).await
227 }
228
229 async fn mark_fts_index_in_flight(&self, batch_id: u64, durable_key: Vec<u8>) {
230 super::fts_handlers::mark_fts_index_in_flight_impl(self, batch_id, durable_key).await
231 }
232
233 async fn ack_fts_index_in_flight(&self, batch_id: u64) {
234 super::fts_handlers::ack_fts_index_in_flight_impl(self, batch_id).await
235 }
236
237 async fn acknowledge_fts_index(&self, durable_key: Vec<u8>) {
238 super::fts_handlers::acknowledge_fts_index_impl(self, durable_key).await
239 }
240
241 async fn pending_fts_deletes(
242 &self,
243 ) -> Result<Vec<(Vec<u8>, crate::sync::outbound::fts::PendingFtsDelete)>, crate::error::LiteError>
244 {
245 super::fts_handlers::pending_fts_deletes_impl(self).await
246 }
247
248 async fn mark_fts_delete_in_flight(&self, batch_id: u64, durable_key: Vec<u8>) {
249 super::fts_handlers::mark_fts_delete_in_flight_impl(self, batch_id, durable_key).await
250 }
251
252 async fn ack_fts_delete_in_flight(&self, batch_id: u64) {
253 super::fts_handlers::ack_fts_delete_in_flight_impl(self, batch_id).await
254 }
255
256 async fn acknowledge_fts_delete(&self, durable_key: Vec<u8>) {
257 super::fts_handlers::acknowledge_fts_delete_impl(self, durable_key).await
258 }
259
260 async fn pending_spatial_inserts(
261 &self,
262 ) -> Vec<(
263 Vec<u8>,
264 crate::sync::outbound::spatial::PendingSpatialInsert,
265 )> {
266 super::spatial_handlers::pending_spatial_inserts_impl(self).await
267 }
268
269 async fn mark_spatial_insert_in_flight(&self, batch_id: u64, durable_key: Vec<u8>) {
270 super::spatial_handlers::mark_spatial_insert_in_flight_impl(self, batch_id, durable_key)
271 .await
272 }
273
274 async fn ack_spatial_insert_in_flight(&self, batch_id: u64) {
275 super::spatial_handlers::ack_spatial_insert_in_flight_impl(self, batch_id).await
276 }
277
278 async fn acknowledge_spatial_insert(&self, durable_key: Vec<u8>) {
279 super::spatial_handlers::acknowledge_spatial_insert_impl(self, durable_key).await
280 }
281
282 async fn pending_spatial_deletes(
283 &self,
284 ) -> Vec<(
285 Vec<u8>,
286 crate::sync::outbound::spatial::PendingSpatialDelete,
287 )> {
288 super::spatial_handlers::pending_spatial_deletes_impl(self).await
289 }
290
291 async fn mark_spatial_delete_in_flight(&self, batch_id: u64, durable_key: Vec<u8>) {
292 super::spatial_handlers::mark_spatial_delete_in_flight_impl(self, batch_id, durable_key)
293 .await
294 }
295
296 async fn ack_spatial_delete_in_flight(&self, batch_id: u64) {
297 super::spatial_handlers::ack_spatial_delete_in_flight_impl(self, batch_id).await
298 }
299
300 async fn acknowledge_spatial_delete(&self, durable_key: Vec<u8>) {
301 super::spatial_handlers::acknowledge_spatial_delete_impl(self, durable_key).await
302 }
303
304 async fn pending_timeseries_batches(
305 &self,
306 ) -> Vec<(
307 Vec<u8>,
308 crate::sync::outbound::timeseries::PendingTimeseriesBatch,
309 )> {
310 super::timeseries_handlers::pending_timeseries_batches_impl(self).await
311 }
312
313 async fn mark_timeseries_batch_in_flight(
314 &self,
315 stream_seq: u64,
316 batch_id: u64,
317 durable_key: Vec<u8>,
318 ) {
319 super::timeseries_handlers::mark_timeseries_batch_in_flight_impl(
320 self,
321 stream_seq,
322 batch_id,
323 durable_key,
324 )
325 .await
326 }
327
328 async fn ack_timeseries_batches_through_seq(&self, applied_seq: u64) {
329 super::timeseries_handlers::ack_timeseries_batches_through_seq_impl(self, applied_seq).await
330 }
331
332 async fn ack_timeseries_batch_by_id(&self, batch_id: u64) {
333 super::timeseries_handlers::ack_timeseries_batch_by_id_impl(self, batch_id).await
334 }
335
336 async fn acknowledge_timeseries_batch(&self, durable_key: Vec<u8>) {
337 super::timeseries_handlers::acknowledge_timeseries_batch_impl(self, durable_key).await
338 }
339
340 async fn pending_kv_writes(
341 &self,
342 ) -> Result<Vec<(Vec<u8>, crate::sync::outbound::kv::PendingKvWrite)>, crate::error::LiteError>
343 {
344 super::kv_handlers::pending_kv_writes_impl(self).await
345 }
346
347 async fn persist_kv_write_seq(
348 &self,
349 key: &[u8],
350 write: &crate::sync::outbound::kv::PendingKvWrite,
351 ) -> Result<(), crate::error::LiteError> {
352 super::kv_handlers::persist_kv_write_seq_impl(self, key, write).await
353 }
354
355 async fn mark_kv_write_in_flight(&self, batch_id: u64) {
356 super::kv_handlers::mark_kv_write_in_flight_impl(self, batch_id).await
357 }
358
359 async fn retire_kv_write(&self, batch_id: u64) -> Result<(), crate::error::LiteError> {
360 super::kv_handlers::retire_kv_write_impl(self, batch_id).await
361 }
362
363 async fn clear_engine_in_flight(&self) {
364 super::outbound_state::clear_engine_in_flight_impl(self).await
365 }
366
367 async fn next_stream_seq(&self, stream_id: u64) -> u64 {
368 super::outbound_state::next_stream_seq_impl(self, stream_id).await
369 }
370
371 async fn record_stream_ack(&self, stream_id: u64, applied_seq: u64) {
372 super::outbound_state::record_stream_ack_impl(self, stream_id, applied_seq).await
373 }
374
375 async fn persist_producer_state(&self, producer_id: u64, accepted_epoch: u64) {
376 super::producer_state::persist_producer_state_impl(self, producer_id, accepted_epoch).await
377 }
378
379 async fn load_producer_state(&self) -> (u64, u64) {
380 super::producer_state::load_producer_state_impl(self).await
381 }
382
383 async fn import_definition(&self, msg: &nodedb_types::sync::wire::DefinitionSyncMsg) {
384 if let Err(e) = super::definition_apply::apply_definition_sync(self, msg).await {
385 tracing::warn!(
386 definition_type = %msg.definition_type,
387 name = %msg.name,
388 error = %e,
389 "definition sync failed"
390 );
391 }
392 }
393
394 async fn import_collection_schema(
395 &self,
396 msg: &nodedb_types::sync::wire::CollectionSchemaSyncMsg,
397 ) {
398 if let Err(e) = self
399 .register_collection_from_descriptor(&msg.descriptor)
400 .await
401 {
402 tracing::warn!(
403 collection = %msg.descriptor.name,
404 error = %e,
405 "collection schema sync failed"
406 );
407 }
408 }
409
410 async fn get_collection_meta(
411 &self,
412 name: &str,
413 ) -> Option<crate::nodedb::collection::CollectionMeta> {
414 super::producer_state::get_collection_meta_impl(self, name).await
415 }
416
417 async fn persist_columnar_seq(
420 &self,
421 key: &[u8],
422 batch: &crate::sync::outbound::columnar::PendingColumnarBatch,
423 ) -> Result<(), crate::error::LiteError> {
424 super::columnar_handlers::persist_columnar_seq_impl(self, key, batch).await
425 }
426
427 async fn persist_timeseries_seq(
428 &self,
429 key: &[u8],
430 batch: &crate::sync::outbound::timeseries::PendingTimeseriesBatch,
431 ) -> Result<(), crate::error::LiteError> {
432 super::timeseries_handlers::persist_timeseries_seq_impl(self, key, batch).await
433 }
434
435 async fn persist_vector_insert_seq(
436 &self,
437 key: &[u8],
438 insert: &crate::sync::outbound::vector::PendingVectorInsert,
439 ) -> Result<(), crate::error::LiteError> {
440 super::vector_handlers::persist_vector_insert_seq_impl(self, key, insert).await
441 }
442
443 async fn persist_vector_delete_seq(
444 &self,
445 key: &[u8],
446 delete: &crate::sync::outbound::vector::PendingVectorDelete,
447 ) -> Result<(), crate::error::LiteError> {
448 super::vector_handlers::persist_vector_delete_seq_impl(self, key, delete).await
449 }
450
451 async fn persist_fts_index_seq(
452 &self,
453 key: &[u8],
454 entry: &crate::sync::outbound::fts::PendingFtsIndex,
455 ) -> Result<(), crate::error::LiteError> {
456 super::fts_handlers::persist_fts_index_seq_impl(self, key, entry).await
457 }
458
459 async fn persist_fts_delete_seq(
460 &self,
461 key: &[u8],
462 entry: &crate::sync::outbound::fts::PendingFtsDelete,
463 ) -> Result<(), crate::error::LiteError> {
464 super::fts_handlers::persist_fts_delete_seq_impl(self, key, entry).await
465 }
466
467 async fn persist_spatial_insert_seq(
468 &self,
469 key: &[u8],
470 insert: &crate::sync::outbound::spatial::PendingSpatialInsert,
471 ) -> Result<(), crate::error::LiteError> {
472 super::spatial_handlers::persist_spatial_insert_seq_impl(self, key, insert).await
473 }
474
475 async fn persist_spatial_delete_seq(
476 &self,
477 key: &[u8],
478 delete: &crate::sync::outbound::spatial::PendingSpatialDelete,
479 ) -> Result<(), crate::error::LiteError> {
480 super::spatial_handlers::persist_spatial_delete_seq_impl(self, key, delete).await
481 }
482}