From 15ffc62279f0352cb0aae408fcfb172686a0ccaa Mon Sep 17 00:00:00 2001 From: "Dustin J. Mitchell" Date: Sun, 10 Jan 2021 21:11:55 -0500 Subject: [PATCH 1/4] rename taskstorage to storage --- cli/src/invocation/test.rs | 4 ++-- docs/src/storage.md | 2 +- taskchampion/src/lib.rs | 4 ++-- taskchampion/src/replica.rs | 6 +++--- .../src/{taskstorage => storage}/inmemory.rs | 10 ++++------ taskchampion/src/{taskstorage => storage}/kv.rs | 12 +++++------- taskchampion/src/{taskstorage => storage}/mod.rs | 12 ++++++------ .../src/{taskstorage => storage}/operation.rs | 2 +- taskchampion/src/task.rs | 2 +- taskchampion/src/taskdb.rs | 14 +++++++------- 10 files changed, 32 insertions(+), 36 deletions(-) rename taskchampion/src/{taskstorage => storage}/inmemory.rs (95%) rename taskchampion/src/{taskstorage => storage}/kv.rs (98%) rename taskchampion/src/{taskstorage => storage}/mod.rs (92%) rename taskchampion/src/{taskstorage => storage}/operation.rs (99%) diff --git a/cli/src/invocation/test.rs b/cli/src/invocation/test.rs index 8f32723b0..6a2cfdaf3 100644 --- a/cli/src/invocation/test.rs +++ b/cli/src/invocation/test.rs @@ -1,9 +1,9 @@ use std::io; -use taskchampion::{server, taskstorage, Replica, ServerConfig}; +use taskchampion::{server, storage, Replica, ServerConfig}; use tempdir::TempDir; pub(super) fn test_replica() -> Replica { - let storage = taskstorage::InMemoryStorage::new(); + let storage = storage::InMemoryStorage::new(); Replica::new(Box::new(storage)) } diff --git a/docs/src/storage.md b/docs/src/storage.md index 977aace74..c1c34f7e1 100644 --- a/docs/src/storage.md +++ b/docs/src/storage.md @@ -1,7 +1,7 @@ # Replica Storage Each replica has a storage backend. -The interface for this backend is given in `crate::taskstorage::TaskStorage` and `TaskStorageTxn`. +The interface for this backend is given in `crate::taskstorage::Storage` and `StorageTxn`. The storage is transaction-protected, with the expectation of a serializable isolation level. The storage contains the following information: diff --git a/taskchampion/src/lib.rs b/taskchampion/src/lib.rs index cdb9e8cc1..dabb9ee1a 100644 --- a/taskchampion/src/lib.rs +++ b/taskchampion/src/lib.rs @@ -9,7 +9,7 @@ synchronize with one another. # Task Storage -The [`taskstorage`](crate::taskstorage) module supports pluggable storage for a replica's data. +The [`storage`](crate::storage) module supports pluggable storage for a replica's data. An implementation is provided, but users of this crate can provide their own implementation as well. # Server @@ -30,7 +30,7 @@ mod replica; pub mod server; mod task; mod taskdb; -pub mod taskstorage; +pub mod storage; mod utils; mod workingset; diff --git a/taskchampion/src/replica.rs b/taskchampion/src/replica.rs index 95cbaf576..39faa205a 100644 --- a/taskchampion/src/replica.rs +++ b/taskchampion/src/replica.rs @@ -3,7 +3,7 @@ use crate::errors::Error; use crate::server::Server; use crate::task::{Status, Task}; use crate::taskdb::TaskDB; -use crate::taskstorage::{KVStorage, Operation, TaskMap, TaskStorage}; +use crate::storage::{KVStorage, Operation, TaskMap, Storage}; use crate::workingset::WorkingSet; use chrono::Utc; use failure::Fallible; @@ -30,7 +30,7 @@ pub struct Replica { } impl Replica { - pub fn new(storage: Box) -> Replica { + pub fn new(storage: Box) -> Replica { Replica { taskdb: TaskDB::new(storage), } @@ -45,7 +45,7 @@ impl Replica { #[cfg(test)] pub fn new_inmemory() -> Replica { - Replica::new(Box::new(crate::taskstorage::InMemoryStorage::new())) + Replica::new(Box::new(crate::storage::InMemoryStorage::new())) } /// Update an existing task. If the value is Some, the property is added or updated. If the diff --git a/taskchampion/src/taskstorage/inmemory.rs b/taskchampion/src/storage/inmemory.rs similarity index 95% rename from taskchampion/src/taskstorage/inmemory.rs rename to taskchampion/src/storage/inmemory.rs index 718ff1b1e..e05f60258 100644 --- a/taskchampion/src/taskstorage/inmemory.rs +++ b/taskchampion/src/storage/inmemory.rs @@ -1,8 +1,6 @@ #![allow(clippy::new_without_default)] -use crate::taskstorage::{ - Operation, TaskMap, TaskStorage, TaskStorageTxn, VersionId, DEFAULT_BASE_VERSION, -}; +use crate::storage::{Operation, Storage, StorageTxn, TaskMap, VersionId, DEFAULT_BASE_VERSION}; use failure::{bail, Fallible}; use std::collections::hash_map::Entry; use std::collections::HashMap; @@ -42,7 +40,7 @@ impl<'t> Txn<'t> { } } -impl<'t> TaskStorageTxn for Txn<'t> { +impl<'t> StorageTxn for Txn<'t> { fn get_task(&mut self, uuid: Uuid) -> Fallible> { match self.data_ref().tasks.get(&uuid) { None => Ok(None), @@ -157,8 +155,8 @@ impl InMemoryStorage { } } -impl TaskStorage for InMemoryStorage { - fn txn<'a>(&'a mut self) -> Fallible> { +impl Storage for InMemoryStorage { + fn txn<'a>(&'a mut self) -> Fallible> { Ok(Box::new(Txn { storage: self, new_data: None, diff --git a/taskchampion/src/taskstorage/kv.rs b/taskchampion/src/storage/kv.rs similarity index 98% rename from taskchampion/src/taskstorage/kv.rs rename to taskchampion/src/storage/kv.rs index 4bbd087be..5a5e06242 100644 --- a/taskchampion/src/taskstorage/kv.rs +++ b/taskchampion/src/storage/kv.rs @@ -1,6 +1,4 @@ -use crate::taskstorage::{ - Operation, TaskMap, TaskStorage, TaskStorageTxn, VersionId, DEFAULT_BASE_VERSION, -}; +use crate::storage::{Operation, Storage, StorageTxn, TaskMap, VersionId, DEFAULT_BASE_VERSION}; use crate::utils::Key; use failure::{bail, Fallible}; use kv::msgpack::Msgpack; @@ -62,8 +60,8 @@ impl<'t> KVStorage<'t> { } } -impl<'t> TaskStorage for KVStorage<'t> { - fn txn<'a>(&'a mut self) -> Fallible> { +impl<'t> Storage for KVStorage<'t> { + fn txn<'a>(&'a mut self) -> Fallible> { Ok(Box::new(Txn { storage: self, txn: Some(self.store.write_txn()?), @@ -104,7 +102,7 @@ impl<'t> Txn<'t> { } } -impl<'t> TaskStorageTxn for Txn<'t> { +impl<'t> StorageTxn for Txn<'t> { fn get_task(&mut self, uuid: Uuid) -> Fallible> { let bucket = self.tasks_bucket(); let buf = match self.kvtxn().get(bucket, uuid.into()) { @@ -356,7 +354,7 @@ impl<'t> TaskStorageTxn for Txn<'t> { #[cfg(test)] mod test { use super::*; - use crate::taskstorage::taskmap_with; + use crate::storage::taskmap_with; use failure::Fallible; use tempdir::TempDir; diff --git a/taskchampion/src/taskstorage/mod.rs b/taskchampion/src/storage/mod.rs similarity index 92% rename from taskchampion/src/taskstorage/mod.rs rename to taskchampion/src/storage/mod.rs index 571c0d8b5..3184831b4 100644 --- a/taskchampion/src/taskstorage/mod.rs +++ b/taskchampion/src/storage/mod.rs @@ -29,7 +29,7 @@ pub use crate::server::VersionId; /// The default for base_version. pub(crate) const DEFAULT_BASE_VERSION: Uuid = crate::server::NO_VERSION_ID; -/// A TaskStorage transaction, in which storage operations are performed. +/// A Storage transaction, in which storage operations are performed. /// /// # Concurrency /// @@ -40,9 +40,9 @@ pub(crate) const DEFAULT_BASE_VERSION: Uuid = crate::server::NO_VERSION_ID; /// # Commiting and Aborting /// /// A transaction is not visible to other readers until it is committed with -/// [`crate::taskstorage::TaskStorageTxn::commit`]. Transactions are aborted if they are dropped. +/// [`crate::storage::StorageTxn::commit`]. Transactions are aborted if they are dropped. /// It is safe and performant to drop transactions that did not modify any data without committing. -pub trait TaskStorageTxn { +pub trait StorageTxn { /// Get an (immutable) task, if it is in the storage fn get_task(&mut self, uuid: Uuid) -> Fallible>; @@ -102,8 +102,8 @@ pub trait TaskStorageTxn { } /// A trait for objects able to act as task storage. Most of the interesting behavior is in the -/// [`crate::taskstorage::TaskStorageTxn`] trait. -pub trait TaskStorage { +/// [`crate::storage::StorageTxn`] trait. +pub trait Storage { /// Begin a transaction - fn txn<'a>(&'a mut self) -> Fallible>; + fn txn<'a>(&'a mut self) -> Fallible>; } diff --git a/taskchampion/src/taskstorage/operation.rs b/taskchampion/src/storage/operation.rs similarity index 99% rename from taskchampion/src/taskstorage/operation.rs rename to taskchampion/src/storage/operation.rs index 665a151ef..fd88e17f9 100644 --- a/taskchampion/src/taskstorage/operation.rs +++ b/taskchampion/src/storage/operation.rs @@ -125,8 +125,8 @@ impl Operation { #[cfg(test)] mod test { use super::*; + use crate::storage::InMemoryStorage; use crate::taskdb::TaskDB; - use crate::taskstorage::InMemoryStorage; use chrono::{Duration, Utc}; use proptest::prelude::*; diff --git a/taskchampion/src/task.rs b/taskchampion/src/task.rs index 1434f452a..fcf47f005 100644 --- a/taskchampion/src/task.rs +++ b/taskchampion/src/task.rs @@ -1,5 +1,5 @@ use crate::replica::Replica; -use crate::taskstorage::TaskMap; +use crate::storage::TaskMap; use chrono::prelude::*; use failure::{format_err, Fallible}; use log::trace; diff --git a/taskchampion/src/taskdb.rs b/taskchampion/src/taskdb.rs index c04a26c36..cdf924ade 100644 --- a/taskchampion/src/taskdb.rs +++ b/taskchampion/src/taskdb.rs @@ -1,6 +1,6 @@ use crate::errors::Error; use crate::server::{AddVersionResult, GetVersionResult, Server}; -use crate::taskstorage::{Operation, TaskMap, TaskStorage, TaskStorageTxn}; +use crate::storage::{Operation, Storage, StorageTxn, TaskMap}; use failure::{format_err, Fallible}; use log::{info, trace, warn}; use serde::{Deserialize, Serialize}; @@ -12,7 +12,7 @@ use uuid::Uuid; /// and so on, and all the invariants that come with it. It leaves the meaning of particular task /// properties to the replica and task implementations. pub struct TaskDB { - storage: Box, + storage: Box, } #[derive(Serialize, Deserialize, Debug)] @@ -22,13 +22,13 @@ struct Version { impl TaskDB { /// Create a new TaskDB with the given backend storage - pub fn new(storage: Box) -> TaskDB { + pub fn new(storage: Box) -> TaskDB { TaskDB { storage } } #[cfg(test)] pub fn new_inmemory() -> TaskDB { - TaskDB::new(Box::new(crate::taskstorage::InMemoryStorage::new())) + TaskDB::new(Box::new(crate::storage::InMemoryStorage::new())) } /// Apply an operation to the TaskDB. Aside from synchronization operations, this is the only way @@ -45,7 +45,7 @@ impl TaskDB { Ok(()) } - fn apply_op(txn: &mut dyn TaskStorageTxn, op: &Operation) -> Fallible<()> { + fn apply_op(txn: &mut dyn StorageTxn, op: &Operation) -> Fallible<()> { match op { Operation::Create { uuid } => { // insert if the task does not already exist @@ -261,7 +261,7 @@ impl TaskDB { Ok(()) } - fn apply_version(txn: &mut dyn TaskStorageTxn, mut version: Version) -> Fallible<()> { + fn apply_version(txn: &mut dyn StorageTxn, mut version: Version) -> Fallible<()> { // The situation here is that the server has already applied all server operations, and we // have already applied all local operations, so states have diverged by several // operations. We need to figure out what operations to apply locally and on the server in @@ -358,7 +358,7 @@ impl TaskDB { mod tests { use super::*; use crate::server::test::TestServer; - use crate::taskstorage::InMemoryStorage; + use crate::storage::InMemoryStorage; use chrono::Utc; use proptest::prelude::*; use std::collections::HashMap; From b004b6cb9367f13ad352098bbf8e90ebb24b71c5 Mon Sep 17 00:00:00 2001 From: "Dustin J. Mitchell" Date: Sun, 10 Jan 2021 21:35:24 -0500 Subject: [PATCH 2/4] use ServerConfig::into_server instead of server::from_config --- cli/src/invocation/mod.rs | 15 ++++++------ cli/src/invocation/test.rs | 9 +++---- taskchampion/src/config.rs | 23 ------------------ taskchampion/src/lib.rs | 12 ++++++++-- taskchampion/src/server/config.rs | 40 +++++++++++++++++++++++++++++++ taskchampion/src/server/mod.rs | 17 ++----------- 6 files changed, 65 insertions(+), 51 deletions(-) create mode 100644 taskchampion/src/server/config.rs diff --git a/cli/src/invocation/mod.rs b/cli/src/invocation/mod.rs index 16c9b0374..b8a44759e 100644 --- a/cli/src/invocation/mod.rs +++ b/cli/src/invocation/mod.rs @@ -3,7 +3,7 @@ use crate::argparse::{Command, Subcommand}; use config::Config; use failure::{format_err, Fallible}; -use taskchampion::{server, Replica, ReplicaConfig, ServerConfig, Uuid}; +use taskchampion::{Replica, ReplicaConfig, Server, ServerConfig, Uuid}; use termcolor::{ColorChoice, StandardStream}; mod cmd; @@ -109,10 +109,10 @@ fn get_replica(settings: &Config) -> Fallible { } /// Get the server for this invocation -fn get_server(settings: &Config) -> Fallible> { +fn get_server(settings: &Config) -> Fallible> { // if server_client_key and server_origin are both set, use // the remote server - if let (Ok(client_key), Ok(origin)) = ( + let config = if let (Ok(client_key), Ok(origin)) = ( settings.get_str("server_client_key"), settings.get_str("server_origin"), ) { @@ -123,16 +123,17 @@ fn get_server(settings: &Config) -> Fallible> { log::debug!("Using sync-server with origin {}", origin); log::debug!("Sync client ID: {}", client_key); - Ok(server::from_config(ServerConfig::Remote { + ServerConfig::Remote { origin, client_key, encryption_secret: encryption_secret.as_bytes().to_vec(), - })?) + } } else { let server_dir = settings.get_str("server_dir")?.into(); log::debug!("Using local sync-server at `{:?}`", server_dir); - Ok(server::from_config(ServerConfig::Local { server_dir })?) - } + ServerConfig::Local { server_dir } + }; + Ok(config.into_server()?) } /// Get a WriteColor implementation based on whether the output is a tty. diff --git a/cli/src/invocation/test.rs b/cli/src/invocation/test.rs index 6a2cfdaf3..5dcac753c 100644 --- a/cli/src/invocation/test.rs +++ b/cli/src/invocation/test.rs @@ -1,5 +1,5 @@ use std::io; -use taskchampion::{server, storage, Replica, ServerConfig}; +use taskchampion::{storage, Replica, Server, ServerConfig}; use tempdir::TempDir; pub(super) fn test_replica() -> Replica { @@ -7,10 +7,11 @@ pub(super) fn test_replica() -> Replica { Replica::new(Box::new(storage)) } -pub(super) fn test_server(dir: &TempDir) -> Box { - server::from_config(ServerConfig::Local { +pub(super) fn test_server(dir: &TempDir) -> Box { + ServerConfig::Local { server_dir: dir.path().to_path_buf(), - }) + } + .into_server() .unwrap() } diff --git a/taskchampion/src/config.rs b/taskchampion/src/config.rs index 63fef6527..d8ebe81fb 100644 --- a/taskchampion/src/config.rs +++ b/taskchampion/src/config.rs @@ -1,30 +1,7 @@ use std::path::PathBuf; -use uuid::Uuid; /// The configuration required for a replica. Use with [`crate::Replica::from_config`]. pub struct ReplicaConfig { /// Path containing the task DB. pub taskdb_dir: PathBuf, } - -/// The configuration for a replica's access to a sync server. Use with -/// [`crate::server::from_config`]. -pub enum ServerConfig { - /// A local task database, for situations with a single replica. - Local { - /// Path containing the server's DB - server_dir: PathBuf, - }, - /// A remote taskchampion-sync-server instance - Remote { - /// Sync server "origin"; a URL with schema and hostname but no path or trailing `/` - origin: String, - - /// Client Key to identify and authenticate this replica to the server - client_key: Uuid, - - /// Private encryption secret used to encrypt all data sent to the server. This can - /// be any suitably un-guessable string of bytes. - encryption_secret: Vec, - }, -} diff --git a/taskchampion/src/lib.rs b/taskchampion/src/lib.rs index dabb9ee1a..f7c896dff 100644 --- a/taskchampion/src/lib.rs +++ b/taskchampion/src/lib.rs @@ -3,10 +3,14 @@ This crate implements the core of TaskChampion, the [replica](crate::Replica). +# Replica + A TaskChampion replica is a local copy of a user's task data. As the name suggests, several replicas of the same data can exist (such as on a user's laptop and on their phone) and can synchronize with one another. +Replicas are accessed using the [`Replica`](crate::replica) type. + # Task Storage The [`storage`](crate::storage) module supports pluggable storage for a replica's data. @@ -15,7 +19,10 @@ An implementation is provided, but users of this crate can provide their own imp # Server Replica synchronization takes place against a server. +Create a server with [`ServerConfig`](crate::ServerConfig). + The [`server`](crate::server) module defines the interface a server must meet. +Users can define their own server impelementations. # See Also @@ -28,14 +35,15 @@ mod config; mod errors; mod replica; pub mod server; +pub mod storage; mod task; mod taskdb; -pub mod storage; mod utils; mod workingset; -pub use config::{ReplicaConfig, ServerConfig}; +pub use config::ReplicaConfig; pub use replica::Replica; +pub use server::{Server, ServerConfig}; pub use task::{Priority, Status, Tag, Task, TaskMut}; pub use workingset::WorkingSet; diff --git a/taskchampion/src/server/config.rs b/taskchampion/src/server/config.rs new file mode 100644 index 000000000..3de8243b4 --- /dev/null +++ b/taskchampion/src/server/config.rs @@ -0,0 +1,40 @@ +use super::types::Server; +use super::{LocalServer, RemoteServer}; +use failure::Fallible; +use std::path::PathBuf; +use uuid::Uuid; + +/// The configuration for a replica's access to a sync server. +pub enum ServerConfig { + /// A local task database, for situations with a single replica. + Local { + /// Path containing the server's DB + server_dir: PathBuf, + }, + /// A remote taskchampion-sync-server instance + Remote { + /// Sync server "origin"; a URL with schema and hostname but no path or trailing `/` + origin: String, + + /// Client Key to identify and authenticate this replica to the server + client_key: Uuid, + + /// Private encryption secret used to encrypt all data sent to the server. This can + /// be any suitably un-guessable string of bytes. + encryption_secret: Vec, + }, +} + +impl ServerConfig { + /// Get a server based on this configuration + pub fn into_server(self) -> Fallible> { + Ok(match self { + ServerConfig::Local { server_dir } => Box::new(LocalServer::new(server_dir)?), + ServerConfig::Remote { + origin, + client_key, + encryption_secret, + } => Box::new(RemoteServer::new(origin, client_key, encryption_secret)), + }) + } +} diff --git a/taskchampion/src/server/mod.rs b/taskchampion/src/server/mod.rs index 40a8d4d2c..21411241c 100644 --- a/taskchampion/src/server/mod.rs +++ b/taskchampion/src/server/mod.rs @@ -1,25 +1,12 @@ -use crate::ServerConfig; -use failure::Fallible; - #[cfg(test)] pub(crate) mod test; +mod config; mod local; mod remote; mod types; +pub use config::ServerConfig; pub use local::LocalServer; pub use remote::RemoteServer; pub use types::*; - -/// Create a new server based on the given configuration. -pub fn from_config(config: ServerConfig) -> Fallible> { - Ok(match config { - ServerConfig::Local { server_dir } => Box::new(LocalServer::new(server_dir)?), - ServerConfig::Remote { - origin, - client_key, - encryption_secret, - } => Box::new(RemoteServer::new(origin, client_key, encryption_secret)), - }) -} From 02d9c577ab233964c0a578bef77c0a9b85424064 Mon Sep 17 00:00:00 2001 From: "Dustin J. Mitchell" Date: Sun, 10 Jan 2021 21:48:28 -0500 Subject: [PATCH 3/4] use StorageConfig instead of ReplicaConfig --- cli/src/invocation/mod.rs | 6 +++--- taskchampion/src/config.rs | 7 ------- taskchampion/src/lib.rs | 3 +-- taskchampion/src/replica.rs | 10 +--------- taskchampion/src/storage/config.rs | 23 +++++++++++++++++++++++ taskchampion/src/storage/mod.rs | 2 ++ 6 files changed, 30 insertions(+), 21 deletions(-) delete mode 100644 taskchampion/src/config.rs create mode 100644 taskchampion/src/storage/config.rs diff --git a/cli/src/invocation/mod.rs b/cli/src/invocation/mod.rs index b8a44759e..32e66a940 100644 --- a/cli/src/invocation/mod.rs +++ b/cli/src/invocation/mod.rs @@ -3,7 +3,7 @@ use crate::argparse::{Command, Subcommand}; use config::Config; use failure::{format_err, Fallible}; -use taskchampion::{Replica, ReplicaConfig, Server, ServerConfig, Uuid}; +use taskchampion::{Replica, Server, ServerConfig, StorageConfig, Uuid}; use termcolor::{ColorChoice, StandardStream}; mod cmd; @@ -104,8 +104,8 @@ pub(crate) fn invoke(command: Command, settings: Config) -> Fallible<()> { fn get_replica(settings: &Config) -> Fallible { let taskdb_dir = settings.get_str("data_dir")?.into(); log::debug!("Replica data_dir: {:?}", taskdb_dir); - let replica_config = ReplicaConfig { taskdb_dir }; - Ok(Replica::from_config(replica_config)?) + let storage_config = StorageConfig::OnDisk { taskdb_dir }; + Ok(Replica::new(storage_config.into_storage()?)) } /// Get the server for this invocation diff --git a/taskchampion/src/config.rs b/taskchampion/src/config.rs deleted file mode 100644 index d8ebe81fb..000000000 --- a/taskchampion/src/config.rs +++ /dev/null @@ -1,7 +0,0 @@ -use std::path::PathBuf; - -/// The configuration required for a replica. Use with [`crate::Replica::from_config`]. -pub struct ReplicaConfig { - /// Path containing the task DB. - pub taskdb_dir: PathBuf, -} diff --git a/taskchampion/src/lib.rs b/taskchampion/src/lib.rs index f7c896dff..9a1cd4635 100644 --- a/taskchampion/src/lib.rs +++ b/taskchampion/src/lib.rs @@ -31,7 +31,6 @@ for more information about the design and usage of the tool. */ -mod config; mod errors; mod replica; pub mod server; @@ -41,9 +40,9 @@ mod taskdb; mod utils; mod workingset; -pub use config::ReplicaConfig; pub use replica::Replica; pub use server::{Server, ServerConfig}; +pub use storage::StorageConfig; pub use task::{Priority, Status, Tag, Task, TaskMut}; pub use workingset::WorkingSet; diff --git a/taskchampion/src/replica.rs b/taskchampion/src/replica.rs index 39faa205a..f13bc19c2 100644 --- a/taskchampion/src/replica.rs +++ b/taskchampion/src/replica.rs @@ -1,9 +1,8 @@ -use crate::config::ReplicaConfig; use crate::errors::Error; use crate::server::Server; +use crate::storage::{Operation, Storage, TaskMap}; use crate::task::{Status, Task}; use crate::taskdb::TaskDB; -use crate::storage::{KVStorage, Operation, TaskMap, Storage}; use crate::workingset::WorkingSet; use chrono::Utc; use failure::Fallible; @@ -36,13 +35,6 @@ impl Replica { } } - /// Construct a new replica from a configuration object. This is the common way - /// to create a new object. - pub fn from_config(config: ReplicaConfig) -> Fallible { - let storage = Box::new(KVStorage::new(config.taskdb_dir)?); - Ok(Replica::new(storage)) - } - #[cfg(test)] pub fn new_inmemory() -> Replica { Replica::new(Box::new(crate::storage::InMemoryStorage::new())) diff --git a/taskchampion/src/storage/config.rs b/taskchampion/src/storage/config.rs new file mode 100644 index 000000000..5ef964575 --- /dev/null +++ b/taskchampion/src/storage/config.rs @@ -0,0 +1,23 @@ +use super::{InMemoryStorage, KVStorage, Storage}; +use failure::Fallible; +use std::path::PathBuf; + +/// The configuration required for a replica's storage. +pub enum StorageConfig { + /// Store the data on disk. This is the common choice. + OnDisk { + /// Path containing the task DB. + taskdb_dir: PathBuf, + }, + /// Store the data in memory. This is only useful for testing. + InMemory, +} + +impl StorageConfig { + pub fn into_storage(self) -> Fallible> { + Ok(match self { + StorageConfig::OnDisk { taskdb_dir } => Box::new(KVStorage::new(taskdb_dir)?), + StorageConfig::InMemory => Box::new(InMemoryStorage::new()), + }) + } +} diff --git a/taskchampion/src/storage/mod.rs b/taskchampion/src/storage/mod.rs index 3184831b4..0932afd3f 100644 --- a/taskchampion/src/storage/mod.rs +++ b/taskchampion/src/storage/mod.rs @@ -2,11 +2,13 @@ use failure::Fallible; use std::collections::HashMap; use uuid::Uuid; +mod config; mod inmemory; mod kv; mod operation; pub use self::kv::KVStorage; +pub use config::StorageConfig; pub use inmemory::InMemoryStorage; pub use operation::Operation; From ae4cee1ac34a0cb3fb0335d115a120ad452c8bb1 Mon Sep 17 00:00:00 2001 From: "Dustin J. Mitchell" Date: Sun, 10 Jan 2021 22:02:42 -0500 Subject: [PATCH 4/4] add docs for the 'server' and 'storage' modules --- taskchampion/src/server/mod.rs | 10 ++++++++++ taskchampion/src/storage/mod.rs | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/taskchampion/src/server/mod.rs b/taskchampion/src/server/mod.rs index 21411241c..68b5a713f 100644 --- a/taskchampion/src/server/mod.rs +++ b/taskchampion/src/server/mod.rs @@ -1,3 +1,13 @@ +/** + +This module defines the client interface to TaskChampion sync servers. +It defines a [trait](crate::server::Server) for servers, and implements both local and remote servers. + +Typical uses of this crate do not interact directly with this module; [`ServerConfig`](crate::ServerConfig) is sufficient. +However, users who wish to implement their own server interfaces can implement the traits defined here and pass the result to [`Replica`](crate::Replica). + +*/ + #[cfg(test)] pub(crate) mod test; diff --git a/taskchampion/src/storage/mod.rs b/taskchampion/src/storage/mod.rs index 0932afd3f..fec354ed2 100644 --- a/taskchampion/src/storage/mod.rs +++ b/taskchampion/src/storage/mod.rs @@ -1,3 +1,12 @@ +/** + +This module defines the backend storage used by [`Replica`](crate::Replica). +It defines a [trait](crate::storage::Storage) for storage implementations, and provides a default on-disk implementation as well as an in-memory implementation for testing. + +Typical uses of this crate do not interact directly with this module; [`StorageConfig`](crate::StorageConfig) is sufficient. +However, users who wish to implement their own storage backends can implement the traits defined here and pass the result to [`Replica`](crate::Replica). + +*/ use failure::Fallible; use std::collections::HashMap; use uuid::Uuid;