mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
Factor replica and sync configuration into simple owned structs
This commit is contained in:
parent
87596bb1f0
commit
8af7ba286d
16 changed files with 81 additions and 23 deletions
|
@ -38,7 +38,7 @@ define_subcommand! {
|
|||
subcommand_invocation! {
|
||||
fn run(&self, command: &CommandInvocation) -> Fallible<()> {
|
||||
let t = command
|
||||
.get_replica()
|
||||
.get_replica()?
|
||||
.new_task(Status::Pending, self.description.clone())
|
||||
.unwrap();
|
||||
println!("added task {}", t.get_uuid());
|
||||
|
|
|
@ -20,7 +20,7 @@ define_subcommand! {
|
|||
|
||||
subcommand_invocation! {
|
||||
fn run(&self, command: &CommandInvocation) -> Fallible<()> {
|
||||
command.get_replica().gc()?;
|
||||
command.get_replica()?.gc()?;
|
||||
println!("garbage collected.");
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ define_subcommand! {
|
|||
|
||||
subcommand_invocation! {
|
||||
fn run(&self, command: &CommandInvocation) -> Fallible<()> {
|
||||
let mut replica = command.get_replica();
|
||||
let mut replica = command.get_replica()?;
|
||||
let task = shared::get_task(&mut replica, &self.task)?;
|
||||
let uuid = task.get_uuid();
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ define_subcommand! {
|
|||
|
||||
subcommand_invocation! {
|
||||
fn run(&self, command: &CommandInvocation) -> Fallible<()> {
|
||||
let mut replica = command.get_replica();
|
||||
let mut replica = command.get_replica()?;
|
||||
let mut t = Table::new();
|
||||
t.set_format(table::format());
|
||||
t.set_titles(row![b->"id", b->"description"]);
|
||||
|
|
|
@ -36,7 +36,7 @@ define_subcommand! {
|
|||
|
||||
subcommand_invocation! {
|
||||
fn run(&self, command: &CommandInvocation) -> Fallible<()> {
|
||||
let mut replica = command.get_replica();
|
||||
let mut replica = command.get_replica()?;
|
||||
let task = shared::get_task(&mut replica, &self.task)?;
|
||||
|
||||
let mut task = task.into_mut(&mut replica);
|
||||
|
|
|
@ -25,7 +25,7 @@ define_subcommand! {
|
|||
|
||||
subcommand_invocation! {
|
||||
fn run(&self, command: &CommandInvocation) -> Fallible<()> {
|
||||
let working_set = command.get_replica().working_set().unwrap();
|
||||
let working_set = command.get_replica()?.working_set().unwrap();
|
||||
let mut t = Table::new();
|
||||
t.set_format(table::format());
|
||||
t.set_titles(row![b->"id", b->"description"]);
|
||||
|
|
|
@ -2,7 +2,7 @@ use clap::Arg;
|
|||
use failure::{format_err, Fallible};
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use taskchampion::{server, taskstorage, Replica, Task, Uuid};
|
||||
use taskchampion::{server, Replica, ReplicaConfig, ServerConfig, Task, Uuid};
|
||||
|
||||
pub(super) fn task_arg<'a>() -> Arg<'a, 'a> {
|
||||
Arg::with_name("task")
|
||||
|
@ -46,20 +46,29 @@ impl CommandInvocation {
|
|||
|
||||
// -- utilities for command invocations
|
||||
|
||||
pub(super) fn get_replica(&self) -> Replica {
|
||||
pub(super) fn get_replica(&self) -> Fallible<Replica> {
|
||||
// temporarily use $TASK_DB to locate the taskdb
|
||||
let taskdb_dir = env::var_os("TASK_DB").unwrap_or_else(|| OsString::from("/tmp/tasks"));
|
||||
Replica::new(Box::new(taskstorage::KVStorage::new(taskdb_dir).unwrap()))
|
||||
let replica_config = ReplicaConfig {
|
||||
taskdb_dir: taskdb_dir.into(),
|
||||
};
|
||||
Ok(Replica::from_config(replica_config)?)
|
||||
}
|
||||
|
||||
pub(super) fn get_server(&self) -> Fallible<impl server::Server> {
|
||||
pub(super) fn get_server(&self) -> Fallible<Box<dyn server::Server>> {
|
||||
// temporarily use $SYNC_SERVER_ORIGIN for the sync server
|
||||
let sync_server_origin = env::var_os("SYNC_SERVER_ORIGIN")
|
||||
let origin = env::var_os("SYNC_SERVER_ORIGIN")
|
||||
.map(|osstr| osstr.into_string().unwrap())
|
||||
.unwrap_or_else(|| String::from("http://localhost:8080"));
|
||||
Ok(server::RemoteServer::new(
|
||||
sync_server_origin,
|
||||
Uuid::parse_str("d5b55cbd-9a82-4860-9a39-41b67893b22f").unwrap(),
|
||||
))
|
||||
let client_id = env::var_os("SYNC_SERVER_CLIENT_ID")
|
||||
.ok_or_else(|| format_err!("SYNC_SERVER_CLIENT_ID not set"))?;
|
||||
let client_id = client_id
|
||||
.into_string()
|
||||
.map_err(|_| format_err!("SYNC_SERVER_CLIENT_ID is not a valid UUID"))?;
|
||||
let client_id = Uuid::parse_str(&client_id)?;
|
||||
Ok(server::from_config(ServerConfig::Remote {
|
||||
origin,
|
||||
client_id,
|
||||
})?)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ define_subcommand! {
|
|||
|
||||
subcommand_invocation! {
|
||||
fn run(&self, command: &CommandInvocation) -> Fallible<()> {
|
||||
let mut replica = command.get_replica();
|
||||
let mut replica = command.get_replica()?;
|
||||
let mut server = command.get_server()?;
|
||||
replica.sync(&mut server)?;
|
||||
Ok(())
|
||||
|
|
|
@ -12,6 +12,7 @@ Note that the `task` interface does not match that of TaskWarrior.
|
|||
Temporarily, configuration is by environment variables.
|
||||
The directory containing the replica's task data is given by `TASK_DB`, defaulting to `/tmp/tasks`.
|
||||
the origin of the sync server is given by `SYNC_SERVER_ORIGIN`, defaulting to `http://localhost:8080`.
|
||||
The client ID to use with the sync server is givne by `SYNC_SERVER_CLIENT_ID` (with no default).
|
||||
|
||||
## `taskchampion-sync-server`
|
||||
|
||||
|
|
26
taskchampion/src/config.rs
Normal file
26
taskchampion/src/config.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
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 ID to identify this replica to the server
|
||||
client_id: Uuid,
|
||||
},
|
||||
}
|
|
@ -23,6 +23,7 @@ for more information about the design and usage of the tool.
|
|||
|
||||
*/
|
||||
|
||||
mod config;
|
||||
mod errors;
|
||||
mod replica;
|
||||
pub mod server;
|
||||
|
@ -31,6 +32,7 @@ mod taskdb;
|
|||
pub mod taskstorage;
|
||||
mod utils;
|
||||
|
||||
pub use config::{ReplicaConfig, ServerConfig};
|
||||
pub use replica::Replica;
|
||||
pub use task::Priority;
|
||||
pub use task::Status;
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use crate::config::ReplicaConfig;
|
||||
use crate::errors::Error;
|
||||
use crate::server::Server;
|
||||
use crate::task::{Status, Task};
|
||||
use crate::taskdb::TaskDB;
|
||||
use crate::taskstorage::{Operation, TaskMap, TaskStorage};
|
||||
use crate::taskstorage::{KVStorage, Operation, TaskMap, TaskStorage};
|
||||
use chrono::Utc;
|
||||
use failure::Fallible;
|
||||
use std::collections::HashMap;
|
||||
|
@ -21,6 +22,11 @@ impl Replica {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_config(config: ReplicaConfig) -> Fallible<Replica> {
|
||||
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::taskstorage::InMemoryStorage::new()))
|
||||
|
@ -140,7 +146,7 @@ impl Replica {
|
|||
}
|
||||
|
||||
/// Synchronize this replica against the given server.
|
||||
pub fn sync(&mut self, server: &mut dyn Server) -> Fallible<()> {
|
||||
pub fn sync(&mut self, server: &mut Box<dyn Server>) -> Fallible<()> {
|
||||
self.taskdb.sync(server)
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ pub struct LocalServer<'t> {
|
|||
|
||||
impl<'t> LocalServer<'t> {
|
||||
/// A test server has no notion of clients, signatures, encryption, etc.
|
||||
pub fn new(directory: &Path) -> Fallible<LocalServer> {
|
||||
pub fn new<P: AsRef<Path>>(directory: P) -> Fallible<LocalServer<'t>> {
|
||||
let mut config = Config::default(directory);
|
||||
config.bucket("versions", None);
|
||||
config.bucket("numbers", None);
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use crate::ServerConfig;
|
||||
use failure::Fallible;
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod test;
|
||||
|
||||
|
@ -8,3 +11,12 @@ mod types;
|
|||
pub use local::LocalServer;
|
||||
pub use remote::RemoteServer;
|
||||
pub use types::*;
|
||||
|
||||
pub fn from_config(config: ServerConfig) -> Fallible<Box<dyn Server>> {
|
||||
Ok(match config {
|
||||
ServerConfig::Local { server_dir } => Box::new(LocalServer::new(server_dir)?),
|
||||
ServerConfig::Remote { origin, client_id } => {
|
||||
Box::new(RemoteServer::new(origin, client_id))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ impl TaskDB {
|
|||
}
|
||||
|
||||
/// Sync to the given server, pulling remote changes and pushing local changes.
|
||||
pub fn sync(&mut self, server: &mut dyn Server) -> Fallible<()> {
|
||||
pub fn sync(&mut self, server: &mut Box<dyn Server>) -> Fallible<()> {
|
||||
let mut txn = self.storage.txn()?;
|
||||
|
||||
// retry synchronizing until the server accepts our version (this allows for races between
|
||||
|
@ -542,7 +542,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_sync() {
|
||||
let mut server = TestServer::new();
|
||||
let mut server: Box<dyn Server> = Box::new(TestServer::new());
|
||||
|
||||
let mut db1 = newdb();
|
||||
db1.sync(&mut server).unwrap();
|
||||
|
@ -602,7 +602,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_sync_create_delete() {
|
||||
let mut server = TestServer::new();
|
||||
let mut server: Box<dyn Server> = Box::new(TestServer::new());
|
||||
|
||||
let mut db1 = newdb();
|
||||
db1.sync(&mut server).unwrap();
|
||||
|
@ -692,7 +692,7 @@ mod tests {
|
|||
// and delete operations that results in a task existing in one TaskDB but not existing in
|
||||
// another. So, the generated sequences focus on a single task UUID.
|
||||
fn transform_sequences_of_operations(action_sequence in action_sequence_strategy()) {
|
||||
let mut server = TestServer::new();
|
||||
let mut server: Box<dyn Server> = Box::new(TestServer::new());
|
||||
let mut dbs = [newdb(), newdb(), newdb()];
|
||||
|
||||
for (action, db) in action_sequence {
|
||||
|
|
|
@ -2,11 +2,13 @@ use failure::Fallible;
|
|||
use std::collections::HashMap;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[cfg(test)]
|
||||
mod inmemory;
|
||||
mod kv;
|
||||
mod operation;
|
||||
|
||||
pub use self::kv::KVStorage;
|
||||
#[cfg(test)]
|
||||
pub use inmemory::InMemoryStorage;
|
||||
|
||||
pub use operation::Operation;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue