summaryrefslogtreecommitdiff
path: root/server/src/play.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/play.rs')
-rw-r--r--server/src/play.rs56
1 files changed, 56 insertions, 0 deletions
diff --git a/server/src/play.rs b/server/src/play.rs
new file mode 100644
index 0000000..8fe1872
--- /dev/null
+++ b/server/src/play.rs
@@ -0,0 +1,56 @@
+use async_trait::async_trait;
+
+use crate::error::BridgeError;
+
+#[async_trait]
+pub trait Journal {
+ // Append payload to the journal at sequence number `seq`.
+ async fn append(&mut self, seq: i64, payload: serde_json::Value) -> Result<(), BridgeError>;
+
+ // Fetch all journal entries with sequence number greater or equal to `seq`.
+ async fn replay(&mut self, seq: i64) -> Result<Vec<serde_json::Value>, BridgeError>;
+}
+
+pub struct Table {}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[derive(Default)]
+ pub struct TestJournal {
+ log: Vec<Option<serde_json::Value>>,
+ }
+
+ #[async_trait]
+ impl Journal for TestJournal {
+ async fn append(
+ &mut self,
+ seq: i64,
+ payload: serde_json::Value,
+ ) -> Result<(), BridgeError> {
+ if seq != self.log.len() as i64 {
+ return Err(BridgeError::UpdateConflict(self.log.len() as i64, seq));
+ }
+ self.log.push(Some(payload));
+ Ok(())
+ }
+
+ async fn replay(&mut self, seq: i64) -> Result<Vec<serde_json::Value>, BridgeError> {
+ Ok(self.log[seq as usize..]
+ .into_iter()
+ .filter_map(|e| e.clone())
+ .collect())
+ }
+ }
+
+ #[tokio::test]
+ async fn test_journal() {
+ use serde_json::json;
+ let mut jnl: TestJournal = Default::default();
+ assert_eq!(jnl.append(0, json!(10)).await.unwrap(), ());
+ assert!(jnl.append(0, json!(0)).await.is_err());
+ assert_eq!(jnl.append(1, json!(20)).await.unwrap(), ());
+ assert_eq!(jnl.replay(1).await.unwrap(), vec!(json!(20)));
+ }
+}