appcore_sync/sync/
outbox.rs1use crate::sync::error::{SyncError, SyncResult};
14use crate::sync::types::SyncMessage;
15use parking_lot::Mutex;
16use std::collections::VecDeque;
17
18pub use crate::sync::outbox_journal::{FileSyncOutbox, SYNC_OUTBOX_FORMAT_V2};
19
20pub trait SyncOutbox: Send + Sync {
22 fn try_enqueue(&self, message: SyncMessage, max_len: usize) -> SyncResult<bool>;
24 fn front(&self) -> SyncResult<Option<SyncMessage>>;
26 fn acknowledge_front(&self, batch_id: &str) -> SyncResult<()>;
28 fn messages(&self) -> SyncResult<Vec<SyncMessage>>;
30 fn len(&self) -> SyncResult<usize>;
32 fn is_empty(&self) -> SyncResult<bool> {
34 Ok(self.len()? == 0)
35 }
36}
37
38#[derive(Debug, Default)]
39pub struct InMemorySyncOutbox {
41 messages: Mutex<VecDeque<SyncMessage>>,
42}
43
44impl InMemorySyncOutbox {
45 pub fn new() -> Self {
47 Self::default()
48 }
49}
50
51impl SyncOutbox for InMemorySyncOutbox {
52 fn try_enqueue(&self, message: SyncMessage, max_len: usize) -> SyncResult<bool> {
53 let mut messages = self.messages.lock();
54 if messages.len() >= max_len {
55 return Ok(false);
56 }
57 messages.push_back(message);
58 Ok(true)
59 }
60
61 fn front(&self) -> SyncResult<Option<SyncMessage>> {
62 Ok(self.messages.lock().front().cloned())
63 }
64
65 fn acknowledge_front(&self, batch_id: &str) -> SyncResult<()> {
66 let mut messages = self.messages.lock();
67 if messages.front().map(|message| message.batch_id.as_str()) != Some(batch_id) {
68 return Err(SyncError::InvalidSyncMessage(
69 "outbox acknowledgement mismatch",
70 ));
71 }
72 messages.pop_front();
73 Ok(())
74 }
75
76 fn messages(&self) -> SyncResult<Vec<SyncMessage>> {
77 Ok(self.messages.lock().iter().cloned().collect())
78 }
79
80 fn len(&self) -> SyncResult<usize> {
81 Ok(self.messages.lock().len())
82 }
83}