diff --git a/taskchampion/src/replica.rs b/taskchampion/src/replica.rs index 7afbc90a3..6bdb756e8 100644 --- a/taskchampion/src/replica.rs +++ b/taskchampion/src/replica.rs @@ -1,6 +1,6 @@ use crate::errors::Error; use crate::server::Server; -use crate::storage::{Operation, Storage, TaskMap}; +use crate::storage::{ReplicaOp, Storage, TaskMap}; use crate::task::{Status, Task}; use crate::taskdb::TaskDb; use crate::workingset::WorkingSet; @@ -56,7 +56,7 @@ impl Replica { S1: Into, S2: Into, { - self.taskdb.apply(Operation::Update { + self.taskdb.apply(ReplicaOp::Update { uuid, property: property.into(), value: value.map(|v| v.into()), @@ -100,7 +100,7 @@ impl Replica { /// Create a new task. The task must not already exist. pub fn new_task(&mut self, status: Status, description: String) -> anyhow::Result { let uuid = Uuid::new_v4(); - self.taskdb.apply(Operation::Create { uuid })?; + self.taskdb.apply(ReplicaOp::Create { uuid })?; trace!("task {} created", uuid); let mut task = Task::new(uuid, TaskMap::new()).into_mut(self); task.set_description(description)?; @@ -118,7 +118,7 @@ impl Replica { if self.taskdb.get_task(uuid)?.is_none() { return Err(Error::Database(format!("Task {} does not exist", uuid)).into()); } - self.taskdb.apply(Operation::Delete { uuid })?; + self.taskdb.apply(ReplicaOp::Delete { uuid })?; trace!("task {} deleted", uuid); Ok(()) } diff --git a/taskchampion/src/storage/inmemory.rs b/taskchampion/src/storage/inmemory.rs index 448d9ae7f..4a4463c19 100644 --- a/taskchampion/src/storage/inmemory.rs +++ b/taskchampion/src/storage/inmemory.rs @@ -1,6 +1,6 @@ #![allow(clippy::new_without_default)] -use crate::storage::{Operation, Storage, StorageTxn, TaskMap, VersionId, DEFAULT_BASE_VERSION}; +use crate::storage::{ReplicaOp, Storage, StorageTxn, TaskMap, VersionId, DEFAULT_BASE_VERSION}; use std::collections::hash_map::Entry; use std::collections::HashMap; use uuid::Uuid; @@ -9,7 +9,7 @@ use uuid::Uuid; struct Data { tasks: HashMap, base_version: VersionId, - operations: Vec, + operations: Vec, working_set: Vec>, } @@ -87,16 +87,16 @@ impl<'t> StorageTxn for Txn<'t> { Ok(()) } - fn operations(&mut self) -> anyhow::Result> { + fn operations(&mut self) -> anyhow::Result> { Ok(self.data_ref().operations.clone()) } - fn add_operation(&mut self, op: Operation) -> anyhow::Result<()> { + fn add_operation(&mut self, op: ReplicaOp) -> anyhow::Result<()> { self.mut_data_ref().operations.push(op); Ok(()) } - fn set_operations(&mut self, ops: Vec) -> anyhow::Result<()> { + fn set_operations(&mut self, ops: Vec) -> anyhow::Result<()> { self.mut_data_ref().operations = ops; Ok(()) } diff --git a/taskchampion/src/storage/mod.rs b/taskchampion/src/storage/mod.rs index a16bb5a7e..d3d494a1b 100644 --- a/taskchampion/src/storage/mod.rs +++ b/taskchampion/src/storage/mod.rs @@ -11,14 +11,14 @@ use uuid::Uuid; mod config; mod inmemory; -mod operation; +mod op; pub(crate) mod sqlite; pub use config::StorageConfig; pub use inmemory::InMemoryStorage; pub use sqlite::SqliteStorage; -pub use operation::Operation; +pub use op::ReplicaOp; /// An in-memory representation of a task as a simple hashmap pub type TaskMap = HashMap; @@ -80,14 +80,14 @@ pub trait StorageTxn { /// Get the current set of outstanding operations (operations that have not been sync'd to the /// server yet) - fn operations(&mut self) -> Result>; + fn operations(&mut self) -> Result>; /// Add an operation to the end of the list of operations in the storage. Note that this /// merely *stores* the operation; it is up to the TaskDb to apply it. - fn add_operation(&mut self, op: Operation) -> Result<()>; + fn add_operation(&mut self, op: ReplicaOp) -> Result<()>; /// Replace the current list of operations with a new list. - fn set_operations(&mut self, ops: Vec) -> Result<()>; + fn set_operations(&mut self, ops: Vec) -> Result<()>; /// Get the entire working set, with each task UUID at its appropriate (1-based) index. /// Element 0 is always None. diff --git a/taskchampion/src/storage/operation.rs b/taskchampion/src/storage/op.rs similarity index 88% rename from taskchampion/src/storage/operation.rs rename to taskchampion/src/storage/op.rs index ed9a5182d..0ab9e1104 100644 --- a/taskchampion/src/storage/operation.rs +++ b/taskchampion/src/storage/op.rs @@ -2,9 +2,10 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use uuid::Uuid; -/// An Operation defines a single change to the task database +/// A ReplicaOp defines a single change to the task database, as stored locally in the replica. +/// This contains additional information not included in SyncOp. #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] -pub enum Operation { +pub enum ReplicaOp { /// Create a new task. /// /// On application, if the task already exists, the operation does nothing. @@ -27,9 +28,9 @@ pub enum Operation { }, } -use Operation::*; +use ReplicaOp::*; -impl Operation { +impl ReplicaOp { // Transform takes two operations A and B that happened concurrently and produces two // operations A' and B' such that `apply(apply(S, A), B') = apply(apply(S, B), A')`. This // function is used to serialize operations in a process similar to a Git "rebase". @@ -53,9 +54,9 @@ impl Operation { // reached different states, to return to the same state by applying op2' and op1', // respectively. pub fn transform( - operation1: Operation, - operation2: Operation, - ) -> (Option, Option) { + operation1: ReplicaOp, + operation2: ReplicaOp, + ) -> (Option, Option) { match (&operation1, &operation2) { // Two creations or deletions of the same uuid reach the same state, so there's no need // for any further operations to bring the state together. @@ -135,13 +136,13 @@ mod test { // thoroughly, so this testing is light. fn test_transform( - setup: Option, - o1: Operation, - o2: Operation, - exp1p: Option, - exp2p: Option, + setup: Option, + o1: ReplicaOp, + o2: ReplicaOp, + exp1p: Option, + exp2p: Option, ) { - let (o1p, o2p) = Operation::transform(o1.clone(), o2.clone()); + let (o1p, o2p) = ReplicaOp::transform(o1.clone(), o2.clone()); assert_eq!((&o1p, &o2p), (&exp1p, &exp2p)); // check that the two operation sequences have the same effect, enforcing the invariant of @@ -349,12 +350,12 @@ mod test { ] } - fn operation_strategy() -> impl Strategy { + fn operation_strategy() -> impl Strategy { prop_oneof![ - uuid_strategy().prop_map(|uuid| Operation::Create { uuid }), - uuid_strategy().prop_map(|uuid| Operation::Delete { uuid }), + uuid_strategy().prop_map(|uuid| ReplicaOp::Create { uuid }), + uuid_strategy().prop_map(|uuid| ReplicaOp::Delete { uuid }), (uuid_strategy(), "(title|project|status)").prop_map(|(uuid, property)| { - Operation::Update { + ReplicaOp::Update { uuid, property, value: Some("true".into()), @@ -372,30 +373,30 @@ mod test { // check that the two operation sequences have the same effect, enforcing the invariant of // the transform function. fn transform_invariant_holds(o1 in operation_strategy(), o2 in operation_strategy()) { - let (o1p, o2p) = Operation::transform(o1.clone(), o2.clone()); + let (o1p, o2p) = ReplicaOp::transform(o1.clone(), o2.clone()); let mut db1 = TaskDb::new(Box::new(InMemoryStorage::new())); let mut db2 = TaskDb::new(Box::new(InMemoryStorage::new())); // Ensure that any expected tasks already exist - if let Operation::Update{ ref uuid, .. } = o1 { - let _ = db1.apply(Operation::Create{uuid: uuid.clone()}); - let _ = db2.apply(Operation::Create{uuid: uuid.clone()}); + if let ReplicaOp::Update{ ref uuid, .. } = o1 { + let _ = db1.apply(ReplicaOp::Create{uuid: uuid.clone()}); + let _ = db2.apply(ReplicaOp::Create{uuid: uuid.clone()}); } - if let Operation::Update{ ref uuid, .. } = o2 { - let _ = db1.apply(Operation::Create{uuid: uuid.clone()}); - let _ = db2.apply(Operation::Create{uuid: uuid.clone()}); + if let ReplicaOp::Update{ ref uuid, .. } = o2 { + let _ = db1.apply(ReplicaOp::Create{uuid: uuid.clone()}); + let _ = db2.apply(ReplicaOp::Create{uuid: uuid.clone()}); } - if let Operation::Delete{ ref uuid } = o1 { - let _ = db1.apply(Operation::Create{uuid: uuid.clone()}); - let _ = db2.apply(Operation::Create{uuid: uuid.clone()}); + if let ReplicaOp::Delete{ ref uuid } = o1 { + let _ = db1.apply(ReplicaOp::Create{uuid: uuid.clone()}); + let _ = db2.apply(ReplicaOp::Create{uuid: uuid.clone()}); } - if let Operation::Delete{ ref uuid } = o2 { - let _ = db1.apply(Operation::Create{uuid: uuid.clone()}); - let _ = db2.apply(Operation::Create{uuid: uuid.clone()}); + if let ReplicaOp::Delete{ ref uuid } = o2 { + let _ = db1.apply(ReplicaOp::Create{uuid: uuid.clone()}); + let _ = db2.apply(ReplicaOp::Create{uuid: uuid.clone()}); } // if applying the initial operations fail, that indicates the operation was invalid diff --git a/taskchampion/src/storage/sqlite.rs b/taskchampion/src/storage/sqlite.rs index 86525d0ca..bf5620af5 100644 --- a/taskchampion/src/storage/sqlite.rs +++ b/taskchampion/src/storage/sqlite.rs @@ -1,4 +1,4 @@ -use crate::storage::{Operation, Storage, StorageTxn, TaskMap, VersionId, DEFAULT_BASE_VERSION}; +use crate::storage::{ReplicaOp, Storage, StorageTxn, TaskMap, VersionId, DEFAULT_BASE_VERSION}; use anyhow::Context; use rusqlite::types::{FromSql, ToSql}; use rusqlite::{params, Connection, OptionalExtension}; @@ -52,17 +52,17 @@ impl ToSql for StoredTaskMap { } } -/// Stores [`Operation`] in SQLite -impl FromSql for Operation { +/// Stores [`ReplicaOp`] in SQLite +impl FromSql for ReplicaOp { fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult { - let o: Operation = serde_json::from_str(value.as_str()?) + let o: ReplicaOp = serde_json::from_str(value.as_str()?) .map_err(|_| rusqlite::types::FromSqlError::InvalidType)?; Ok(o) } } -/// Parsers Operation stored as JSON in string column -impl ToSql for Operation { +/// Parses ReplicaOp stored as JSON in string column +impl ToSql for ReplicaOp { fn to_sql(&self) -> rusqlite::Result> { let s = serde_json::to_string(&self) .map_err(|e| rusqlite::Error::ToSqlConversionFailure(Box::new(e)))?; @@ -241,12 +241,12 @@ impl<'t> StorageTxn for Txn<'t> { Ok(()) } - fn operations(&mut self) -> anyhow::Result> { + fn operations(&mut self) -> anyhow::Result> { let t = self.get_txn()?; let mut q = t.prepare("SELECT data FROM operations ORDER BY id ASC")?; let rows = q.query_map([], |r| { - let data: Operation = r.get("data")?; + let data: ReplicaOp = r.get("data")?; Ok(data) })?; @@ -257,7 +257,7 @@ impl<'t> StorageTxn for Txn<'t> { Ok(ret) } - fn add_operation(&mut self, op: Operation) -> anyhow::Result<()> { + fn add_operation(&mut self, op: ReplicaOp) -> anyhow::Result<()> { let t = self.get_txn()?; t.execute("INSERT INTO operations (data) VALUES (?)", params![&op]) @@ -265,7 +265,7 @@ impl<'t> StorageTxn for Txn<'t> { Ok(()) } - fn set_operations(&mut self, ops: Vec) -> anyhow::Result<()> { + fn set_operations(&mut self, ops: Vec) -> anyhow::Result<()> { let t = self.get_txn()?; t.execute("DELETE FROM operations", []) .context("Clear all existing operations")?; @@ -611,8 +611,8 @@ mod test { // create some operations { let mut txn = storage.txn()?; - txn.add_operation(Operation::Create { uuid: uuid1 })?; - txn.add_operation(Operation::Create { uuid: uuid2 })?; + txn.add_operation(ReplicaOp::Create { uuid: uuid1 })?; + txn.add_operation(ReplicaOp::Create { uuid: uuid2 })?; txn.commit()?; } @@ -623,8 +623,8 @@ mod test { assert_eq!( ops, vec![ - Operation::Create { uuid: uuid1 }, - Operation::Create { uuid: uuid2 }, + ReplicaOp::Create { uuid: uuid1 }, + ReplicaOp::Create { uuid: uuid2 }, ] ); } @@ -633,8 +633,8 @@ mod test { { let mut txn = storage.txn()?; txn.set_operations(vec![ - Operation::Delete { uuid: uuid2 }, - Operation::Delete { uuid: uuid1 }, + ReplicaOp::Delete { uuid: uuid2 }, + ReplicaOp::Delete { uuid: uuid1 }, ])?; txn.commit()?; } @@ -642,8 +642,8 @@ mod test { // create some more operations (to test adding operations after clearing) { let mut txn = storage.txn()?; - txn.add_operation(Operation::Create { uuid: uuid3 })?; - txn.add_operation(Operation::Delete { uuid: uuid3 })?; + txn.add_operation(ReplicaOp::Create { uuid: uuid3 })?; + txn.add_operation(ReplicaOp::Delete { uuid: uuid3 })?; txn.commit()?; } @@ -654,10 +654,10 @@ mod test { assert_eq!( ops, vec![ - Operation::Delete { uuid: uuid2 }, - Operation::Delete { uuid: uuid1 }, - Operation::Create { uuid: uuid3 }, - Operation::Delete { uuid: uuid3 }, + ReplicaOp::Delete { uuid: uuid2 }, + ReplicaOp::Delete { uuid: uuid1 }, + ReplicaOp::Create { uuid: uuid3 }, + ReplicaOp::Delete { uuid: uuid3 }, ] ); } diff --git a/taskchampion/src/taskdb/mod.rs b/taskchampion/src/taskdb/mod.rs index 026e82698..bd886c29b 100644 --- a/taskchampion/src/taskdb/mod.rs +++ b/taskchampion/src/taskdb/mod.rs @@ -1,5 +1,5 @@ use crate::server::{Server, SyncOp}; -use crate::storage::{Operation, Storage, TaskMap}; +use crate::storage::{ReplicaOp, Storage, TaskMap}; use uuid::Uuid; mod ops; @@ -31,7 +31,7 @@ impl TaskDb { /// Apply an operation to the TaskDb. Aside from synchronization operations, this is the only way /// to modify the TaskDb. In cases where an operation does not make sense, this function will do /// nothing and return an error (but leave the TaskDb in a consistent state). - pub fn apply(&mut self, op: Operation) -> anyhow::Result<()> { + pub fn apply(&mut self, op: ReplicaOp) -> anyhow::Result<()> { // TODO: differentiate error types here? let mut txn = self.storage.txn()?; if let err @ Err(_) = ops::apply_op(txn.as_mut(), &op) { @@ -46,14 +46,14 @@ impl TaskDb { pub fn apply_sync_tmp(&mut self, op: SyncOp) -> anyhow::Result<()> { // create an op from SyncOp let op = match op { - SyncOp::Create { uuid } => Operation::Create { uuid }, - SyncOp::Delete { uuid } => Operation::Delete { uuid }, + SyncOp::Create { uuid } => ReplicaOp::Create { uuid }, + SyncOp::Delete { uuid } => ReplicaOp::Delete { uuid }, SyncOp::Update { uuid, property, value, timestamp, - } => Operation::Update { + } => ReplicaOp::Update { uuid, property, value, @@ -158,7 +158,7 @@ impl TaskDb { } #[cfg(test)] - pub(crate) fn operations(&mut self) -> Vec { + pub(crate) fn operations(&mut self) -> Vec { let mut txn = self.storage.txn().unwrap(); txn.operations() .unwrap() @@ -184,7 +184,7 @@ mod tests { // operations; more detailed tests are in the `ops` module. let mut db = TaskDb::new_inmemory(); let uuid = Uuid::new_v4(); - let op = Operation::Create { uuid }; + let op = ReplicaOp::Create { uuid }; db.apply(op.clone()).unwrap(); assert_eq!(db.sorted_tasks(), vec![(uuid, vec![]),]); @@ -197,7 +197,7 @@ mod tests { #[derive(Debug)] enum Action { - Op(Operation), + Op(ReplicaOp), Sync, } @@ -209,14 +209,14 @@ mod tests { .chunks(2) .map(|action_on| { let action = match action_on[0] { - b'C' => Action::Op(Operation::Create { uuid }), - b'U' => Action::Op(Operation::Update { + b'C' => Action::Op(ReplicaOp::Create { uuid }), + b'U' => Action::Op(ReplicaOp::Update { uuid, property: "title".into(), value: Some("foo".into()), timestamp: Utc::now(), }), - b'D' => Action::Op(Operation::Delete { uuid }), + b'D' => Action::Op(ReplicaOp::Delete { uuid }), b'S' => Action::Sync, _ => unreachable!(), }; diff --git a/taskchampion/src/taskdb/ops.rs b/taskchampion/src/taskdb/ops.rs index 7e23d04ce..45c66cb0c 100644 --- a/taskchampion/src/taskdb/ops.rs +++ b/taskchampion/src/taskdb/ops.rs @@ -1,20 +1,20 @@ use crate::errors::Error; -use crate::storage::{Operation, StorageTxn}; +use crate::storage::{ReplicaOp, StorageTxn}; -pub(super) fn apply_op(txn: &mut dyn StorageTxn, op: &Operation) -> anyhow::Result<()> { +pub(super) fn apply_op(txn: &mut dyn StorageTxn, op: &ReplicaOp) -> anyhow::Result<()> { match op { - Operation::Create { uuid } => { + ReplicaOp::Create { uuid } => { // insert if the task does not already exist if !txn.create_task(*uuid)? { return Err(Error::Database(format!("Task {} already exists", uuid)).into()); } } - Operation::Delete { ref uuid } => { + ReplicaOp::Delete { ref uuid } => { if !txn.delete_task(*uuid)? { return Err(Error::Database(format!("Task {} does not exist", uuid)).into()); } } - Operation::Update { + ReplicaOp::Update { ref uuid, ref property, ref value, @@ -49,7 +49,7 @@ mod tests { fn test_apply_create() -> anyhow::Result<()> { let mut db = TaskDb::new_inmemory(); let uuid = Uuid::new_v4(); - let op = Operation::Create { uuid }; + let op = ReplicaOp::Create { uuid }; { let mut txn = db.storage.txn()?; @@ -65,7 +65,7 @@ mod tests { fn test_apply_create_exists() -> anyhow::Result<()> { let mut db = TaskDb::new_inmemory(); let uuid = Uuid::new_v4(); - let op = Operation::Create { uuid }; + let op = ReplicaOp::Create { uuid }; { let mut txn = db.storage.txn()?; apply_op(txn.as_mut(), &op)?; @@ -86,7 +86,7 @@ mod tests { fn test_apply_create_update() -> anyhow::Result<()> { let mut db = TaskDb::new_inmemory(); let uuid = Uuid::new_v4(); - let op1 = Operation::Create { uuid }; + let op1 = ReplicaOp::Create { uuid }; { let mut txn = db.storage.txn()?; @@ -94,7 +94,7 @@ mod tests { txn.commit()?; } - let op2 = Operation::Update { + let op2 = ReplicaOp::Update { uuid, property: String::from("title"), value: Some("my task".into()), @@ -118,14 +118,14 @@ mod tests { fn test_apply_create_update_delete_prop() -> anyhow::Result<()> { let mut db = TaskDb::new_inmemory(); let uuid = Uuid::new_v4(); - let op1 = Operation::Create { uuid }; + let op1 = ReplicaOp::Create { uuid }; { let mut txn = db.storage.txn()?; apply_op(txn.as_mut(), &op1)?; txn.commit()?; } - let op2 = Operation::Update { + let op2 = ReplicaOp::Update { uuid, property: String::from("title"), value: Some("my task".into()), @@ -137,7 +137,7 @@ mod tests { txn.commit()?; } - let op3 = Operation::Update { + let op3 = ReplicaOp::Update { uuid, property: String::from("priority"), value: Some("H".into()), @@ -149,7 +149,7 @@ mod tests { txn.commit()?; } - let op4 = Operation::Update { + let op4 = ReplicaOp::Update { uuid, property: String::from("title"), value: None, @@ -177,7 +177,7 @@ mod tests { fn test_apply_update_does_not_exist() -> anyhow::Result<()> { let mut db = TaskDb::new_inmemory(); let uuid = Uuid::new_v4(); - let op = Operation::Update { + let op = ReplicaOp::Update { uuid, property: String::from("title"), value: Some("my task".into()), @@ -199,8 +199,8 @@ mod tests { fn test_apply_create_delete() -> anyhow::Result<()> { let mut db = TaskDb::new_inmemory(); let uuid = Uuid::new_v4(); - let op1 = Operation::Create { uuid }; - let op2 = Operation::Delete { uuid }; + let op1 = ReplicaOp::Create { uuid }; + let op2 = ReplicaOp::Delete { uuid }; { let mut txn = db.storage.txn()?; @@ -218,7 +218,7 @@ mod tests { fn test_apply_delete_not_present() -> anyhow::Result<()> { let mut db = TaskDb::new_inmemory(); let uuid = Uuid::new_v4(); - let op = Operation::Delete { uuid }; + let op = ReplicaOp::Delete { uuid }; { let mut txn = db.storage.txn()?; assert_eq!( diff --git a/taskchampion/src/taskdb/sync.rs b/taskchampion/src/taskdb/sync.rs index 7ce1d76ce..f5806656a 100644 --- a/taskchampion/src/taskdb/sync.rs +++ b/taskchampion/src/taskdb/sync.rs @@ -1,6 +1,6 @@ use super::{ops, snapshot}; use crate::server::{AddVersionResult, GetVersionResult, Server, SnapshotUrgency}; -use crate::storage::{Operation, StorageTxn}; +use crate::storage::{ReplicaOp, StorageTxn}; use crate::Error; use log::{info, trace, warn}; use serde::{Deserialize, Serialize}; @@ -8,7 +8,7 @@ use std::str; #[derive(Serialize, Deserialize, Debug)] struct Version { - operations: Vec, + operations: Vec, } /// Sync to the given server, pulling remote changes and pushing local changes. @@ -58,7 +58,7 @@ pub(super) fn sync( } } - let operations: Vec = txn.operations()?.to_vec(); + let operations: Vec = txn.operations()?.to_vec(); if operations.is_empty() { info!("no changes to push to server"); // nothing to sync back to the server.. @@ -136,7 +136,7 @@ fn apply_version(txn: &mut dyn StorageTxn, mut version: Version) -> anyhow::Resu // This is slightly complicated by the fact that the transform function can return None, // indicating no operation is required. If this happens for a local op, we can just omit // it. If it happens for server op, then we must copy the remaining local ops. - let mut local_operations: Vec = txn.operations()?; + let mut local_operations: Vec = txn.operations()?; for server_op in version.operations.drain(..) { trace!( "rebasing local operations onto server operation {:?}", @@ -146,7 +146,7 @@ fn apply_version(txn: &mut dyn StorageTxn, mut version: Version) -> anyhow::Resu let mut svr_op = Some(server_op); for local_op in local_operations.drain(..) { if let Some(o) = svr_op { - let (new_server_op, new_local_op) = Operation::transform(o, local_op.clone()); + let (new_server_op, new_local_op) = ReplicaOp::transform(o, local_op.clone()); trace!("local operation {:?} -> {:?}", local_op, new_local_op); svr_op = new_server_op; if let Some(o) = new_local_op { @@ -175,7 +175,7 @@ fn apply_version(txn: &mut dyn StorageTxn, mut version: Version) -> anyhow::Resu mod test { use super::*; use crate::server::test::TestServer; - use crate::storage::{InMemoryStorage, Operation}; + use crate::storage::{InMemoryStorage, ReplicaOp}; use crate::taskdb::{snapshot::SnapshotTasks, TaskDb}; use chrono::Utc; use pretty_assertions::assert_eq; @@ -197,8 +197,8 @@ mod test { // make some changes in parallel to db1 and db2.. let uuid1 = Uuid::new_v4(); - db1.apply(Operation::Create { uuid: uuid1 }).unwrap(); - db1.apply(Operation::Update { + db1.apply(ReplicaOp::Create { uuid: uuid1 }).unwrap(); + db1.apply(ReplicaOp::Update { uuid: uuid1, property: "title".into(), value: Some("my first task".into()), @@ -207,8 +207,8 @@ mod test { .unwrap(); let uuid2 = Uuid::new_v4(); - db2.apply(Operation::Create { uuid: uuid2 }).unwrap(); - db2.apply(Operation::Update { + db2.apply(ReplicaOp::Create { uuid: uuid2 }).unwrap(); + db2.apply(ReplicaOp::Update { uuid: uuid2, property: "title".into(), value: Some("my second task".into()), @@ -223,14 +223,14 @@ mod test { assert_eq!(db1.sorted_tasks(), db2.sorted_tasks()); // now make updates to the same task on both sides - db1.apply(Operation::Update { + db1.apply(ReplicaOp::Update { uuid: uuid2, property: "priority".into(), value: Some("H".into()), timestamp: Utc::now(), }) .unwrap(); - db2.apply(Operation::Update { + db2.apply(ReplicaOp::Update { uuid: uuid2, property: "project".into(), value: Some("personal".into()), @@ -259,8 +259,8 @@ mod test { // create and update a task.. let uuid = Uuid::new_v4(); - db1.apply(Operation::Create { uuid }).unwrap(); - db1.apply(Operation::Update { + db1.apply(ReplicaOp::Create { uuid }).unwrap(); + db1.apply(ReplicaOp::Update { uuid, property: "title".into(), value: Some("my first task".into()), @@ -275,9 +275,9 @@ mod test { assert_eq!(db1.sorted_tasks(), db2.sorted_tasks()); // delete and re-create the task on db1 - db1.apply(Operation::Delete { uuid }).unwrap(); - db1.apply(Operation::Create { uuid }).unwrap(); - db1.apply(Operation::Update { + db1.apply(ReplicaOp::Delete { uuid }).unwrap(); + db1.apply(ReplicaOp::Create { uuid }).unwrap(); + db1.apply(ReplicaOp::Update { uuid, property: "title".into(), value: Some("my second task".into()), @@ -286,7 +286,7 @@ mod test { .unwrap(); // and on db2, update a property of the task - db2.apply(Operation::Update { + db2.apply(ReplicaOp::Update { uuid, property: "project".into(), value: Some("personal".into()), @@ -310,8 +310,8 @@ mod test { let mut db1 = newdb(); let uuid = Uuid::new_v4(); - db1.apply(Operation::Create { uuid })?; - db1.apply(Operation::Update { + db1.apply(ReplicaOp::Create { uuid })?; + db1.apply(ReplicaOp::Update { uuid, property: "title".into(), value: Some("my first task".into()), @@ -332,7 +332,7 @@ mod test { assert_eq!(tasks[0].0, uuid); // update the taskdb and sync again - db1.apply(Operation::Update { + db1.apply(ReplicaOp::Update { uuid, property: "title".into(), value: Some("my first task, updated".into()), @@ -362,7 +362,7 @@ mod test { let mut db1 = newdb(); let uuid = Uuid::new_v4(); - db1.apply(Operation::Create { uuid }).unwrap(); + db1.apply(ReplicaOp::Create { uuid }).unwrap(); test_server.set_snapshot_urgency(SnapshotUrgency::Low); sync(&mut server, db1.storage.txn()?.as_mut(), true).unwrap(); diff --git a/taskchampion/src/taskdb/working_set.rs b/taskchampion/src/taskdb/working_set.rs index d5e0774b0..dc0680ceb 100644 --- a/taskchampion/src/taskdb/working_set.rs +++ b/taskchampion/src/taskdb/working_set.rs @@ -63,7 +63,7 @@ where #[cfg(test)] mod test { use super::*; - use crate::storage::Operation; + use crate::storage::ReplicaOp; use crate::taskdb::TaskDb; use chrono::Utc; use uuid::Uuid; @@ -94,10 +94,10 @@ mod test { // add everything to the TaskDb for uuid in &uuids { - db.apply(Operation::Create { uuid: *uuid })?; + db.apply(ReplicaOp::Create { uuid: *uuid })?; } for i in &[0usize, 1, 4] { - db.apply(Operation::Update { + db.apply(ReplicaOp::Update { uuid: uuids[*i].clone(), property: String::from("status"), value: Some("pending".into()),