Add option to not create new clients
This commit is contained in:
parent
1ed97d6b83
commit
ed9d885bed
@ -52,7 +52,9 @@ pub(crate) async fn service(
|
|||||||
let mut txn = server_state.storage.txn().map_err(failure_to_ise)?;
|
let mut txn = server_state.storage.txn().map_err(failure_to_ise)?;
|
||||||
|
|
||||||
// get, or create, the client
|
// get, or create, the client
|
||||||
let client = match txn.get_client(client_id).map_err(failure_to_ise)? {
|
let client;
|
||||||
|
if server_state.config.create_client_on_request {
|
||||||
|
client = match txn.get_client(client_id).map_err(failure_to_ise)? {
|
||||||
Some(client) => client,
|
Some(client) => client,
|
||||||
None => {
|
None => {
|
||||||
txn.new_client(client_id, NIL_VERSION_ID)
|
txn.new_client(client_id, NIL_VERSION_ID)
|
||||||
@ -60,6 +62,12 @@ pub(crate) async fn service(
|
|||||||
txn.get_client(client_id).map_err(failure_to_ise)?.unwrap()
|
txn.get_client(client_id).map_err(failure_to_ise)?.unwrap()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
client = txn
|
||||||
|
.get_client(client_id)
|
||||||
|
.map_err(failure_to_ise)?
|
||||||
|
.ok_or_else(|| error::ErrorNotFound("no such client"))?;
|
||||||
|
}
|
||||||
|
|
||||||
add_snapshot(
|
add_snapshot(
|
||||||
txn,
|
txn,
|
||||||
|
@ -60,7 +60,9 @@ pub(crate) async fn service(
|
|||||||
let mut txn = server_state.storage.txn().map_err(failure_to_ise)?;
|
let mut txn = server_state.storage.txn().map_err(failure_to_ise)?;
|
||||||
|
|
||||||
// get, or create, the client
|
// get, or create, the client
|
||||||
let client = match txn.get_client(client_id).map_err(failure_to_ise)? {
|
let client;
|
||||||
|
if server_state.config.create_client_on_request {
|
||||||
|
client = match txn.get_client(client_id).map_err(failure_to_ise)? {
|
||||||
Some(client) => client,
|
Some(client) => client,
|
||||||
None => {
|
None => {
|
||||||
txn.new_client(client_id, NIL_VERSION_ID)
|
txn.new_client(client_id, NIL_VERSION_ID)
|
||||||
@ -68,6 +70,12 @@ pub(crate) async fn service(
|
|||||||
txn.get_client(client_id).map_err(failure_to_ise)?.unwrap()
|
txn.get_client(client_id).map_err(failure_to_ise)?.unwrap()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
client = txn
|
||||||
|
.get_client(client_id)
|
||||||
|
.map_err(failure_to_ise)?
|
||||||
|
.ok_or_else(|| error::ErrorNotFound("no such client"))?;
|
||||||
|
}
|
||||||
|
|
||||||
let (result, snap_urgency) = add_version(
|
let (result, snap_urgency) = add_version(
|
||||||
txn,
|
txn,
|
||||||
|
@ -2,49 +2,88 @@
|
|||||||
|
|
||||||
use actix_web::{middleware::Logger, App, HttpServer};
|
use actix_web::{middleware::Logger, App, HttpServer};
|
||||||
use clap::{arg, builder::ValueParser, value_parser, Command};
|
use clap::{arg, builder::ValueParser, value_parser, Command};
|
||||||
|
use uuid::Uuid;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use taskchampion_sync_server::storage::SqliteStorage;
|
use std::path::{Path, PathBuf};
|
||||||
|
use taskchampion_sync_server::storage::{SqliteStorage, Storage};
|
||||||
use taskchampion_sync_server::{Server, ServerConfig};
|
use taskchampion_sync_server::{Server, ServerConfig};
|
||||||
|
|
||||||
#[actix_web::main]
|
#[actix_web::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let defaults = ServerConfig::default();
|
let defaults = ServerConfig::default();
|
||||||
let default_snapshot_versions = defaults.snapshot_versions.to_string();
|
|
||||||
let default_snapshot_days = defaults.snapshot_days.to_string();
|
let config_arg = arg!(-c --config <PATH> "Config file")
|
||||||
|
.default_value(PathBuf::from(&defaults.data_dir).join("config").to_string_lossy().to_string());
|
||||||
|
|
||||||
let matches = Command::new("taskchampion-sync-server")
|
let matches = Command::new("taskchampion-sync-server")
|
||||||
.version(env!("CARGO_PKG_VERSION"))
|
.version(env!("CARGO_PKG_VERSION"))
|
||||||
.about("Server for TaskChampion")
|
.about("Server for TaskChampion")
|
||||||
.arg(
|
.arg(&config_arg)
|
||||||
arg!(-p --port <PORT> "Port on which to serve")
|
|
||||||
.help("Port on which to serve")
|
|
||||||
.value_parser(value_parser!(usize))
|
|
||||||
.default_value("8080"),
|
|
||||||
)
|
|
||||||
.arg(
|
.arg(
|
||||||
arg!(-d --"data-dir" <DIR> "Directory in which to store data")
|
arg!(-d --"data-dir" <DIR> "Directory in which to store data")
|
||||||
.value_parser(ValueParser::os_string())
|
.value_parser(ValueParser::os_string())
|
||||||
.default_value("/var/lib/taskchampion-sync-server"),
|
.default_value(&defaults.data_dir),
|
||||||
|
)
|
||||||
|
.subcommand(
|
||||||
|
Command::new("clients")
|
||||||
|
.subcommand(Command::new("list"))
|
||||||
|
.subcommand(Command::new("add").arg(arg!(<CLIENT_ID>)))
|
||||||
|
.subcommand(Command::new("remove").arg(arg!(<CLIENT_ID>)))
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
arg!(-p --port <PORT> "Port on which to serve")
|
||||||
|
.value_parser(value_parser!(u16))
|
||||||
|
.default_value(defaults.port.to_string()),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
arg!(--"snapshot-versions" <NUM> "Target number of versions between snapshots")
|
arg!(--"snapshot-versions" <NUM> "Target number of versions between snapshots")
|
||||||
.value_parser(value_parser!(u32))
|
.value_parser(value_parser!(u32))
|
||||||
.default_value(default_snapshot_versions),
|
.default_value(defaults.snapshot_versions.to_string()),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
arg!(--"snapshot-days" <NUM> "Target number of days between snapshots")
|
arg!(--"snapshot-days" <NUM> "Target number of days between snapshots")
|
||||||
.value_parser(value_parser!(i64))
|
.value_parser(value_parser!(i64))
|
||||||
.default_value(default_snapshot_days),
|
.default_value(defaults.snapshot_days.to_string()),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let data_dir: &OsString = matches.get_one("data-dir").unwrap();
|
let data_dir: &OsString = matches.get_one("data-dir").unwrap();
|
||||||
let port: usize = *matches.get_one("port").unwrap();
|
// TODO: let config_path: &String = matches.get_one("config").unwrap();
|
||||||
|
|
||||||
|
let storage = SqliteStorage::new(data_dir)?;
|
||||||
|
|
||||||
|
match matches.subcommand() {
|
||||||
|
Some(("clients", sub_matches)) => {
|
||||||
|
|
||||||
|
match sub_matches.subcommand() {
|
||||||
|
Some(("add", sub_matches)) => {
|
||||||
|
let client_id = sub_matches.get_one::<String>("CLIENT_ID").unwrap();
|
||||||
|
let client_id = Uuid::parse_str(client_id)?;
|
||||||
|
let mut t = storage.txn()?;
|
||||||
|
t.new_client(client_id, Uuid::nil())?
|
||||||
|
},
|
||||||
|
Some(("remove", _sub_matches)) => {
|
||||||
|
todo!()
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
let mut t = storage.txn()?;
|
||||||
|
for client in t.list_clients()? {
|
||||||
|
print!("{client}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let port: u16 = *matches.get_one("port").unwrap();
|
||||||
let snapshot_versions: u32 = *matches.get_one("snapshot-versions").unwrap();
|
let snapshot_versions: u32 = *matches.get_one("snapshot-versions").unwrap();
|
||||||
let snapshot_days: i64 = *matches.get_one("snapshot-days").unwrap();
|
let snapshot_days: i64 = *matches.get_one("snapshot-days").unwrap();
|
||||||
|
|
||||||
let config = ServerConfig::from_args(snapshot_days, snapshot_versions)?;
|
let data_dir_owned = data_dir.to_string_lossy().into();
|
||||||
let server = Server::new(config, Box::new(SqliteStorage::new(data_dir)?));
|
let mut config = ServerConfig::from_args(snapshot_days, snapshot_versions, port, data_dir_owned)?;
|
||||||
|
config.create_client_on_request = false;
|
||||||
|
|
||||||
|
let server = Server::new(config, Box::new(storage));
|
||||||
|
|
||||||
log::warn!("Serving on port {}", port);
|
log::warn!("Serving on port {}", port);
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
@ -55,6 +94,10 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
.bind(format!("0.0.0.0:{}", port))?
|
.bind(format!("0.0.0.0:{}", port))?
|
||||||
.run()
|
.run()
|
||||||
.await?;
|
.await?;
|
||||||
|
},
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,12 @@ pub struct ServerConfig {
|
|||||||
|
|
||||||
/// Target number of versions between snapshots.
|
/// Target number of versions between snapshots.
|
||||||
pub snapshot_versions: u32,
|
pub snapshot_versions: u32,
|
||||||
|
|
||||||
|
pub port: u16,
|
||||||
|
|
||||||
|
pub data_dir: String,
|
||||||
|
|
||||||
|
pub create_client_on_request: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ServerConfig {
|
impl Default for ServerConfig {
|
||||||
@ -31,15 +37,21 @@ impl Default for ServerConfig {
|
|||||||
ServerConfig {
|
ServerConfig {
|
||||||
snapshot_days: 14,
|
snapshot_days: 14,
|
||||||
snapshot_versions: 100,
|
snapshot_versions: 100,
|
||||||
|
port: 8080,
|
||||||
|
data_dir: String::from("/var/lib/taskchampion-sync-server"),
|
||||||
|
create_client_on_request: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerConfig {
|
impl ServerConfig {
|
||||||
pub fn from_args(snapshot_days: i64, snapshot_versions: u32) -> anyhow::Result<ServerConfig> {
|
pub fn from_args(snapshot_days: i64, snapshot_versions: u32, port: u16, data_dir: String) -> anyhow::Result<ServerConfig> {
|
||||||
Ok(ServerConfig {
|
Ok(ServerConfig {
|
||||||
snapshot_days,
|
snapshot_days,
|
||||||
snapshot_versions,
|
snapshot_versions,
|
||||||
|
port,
|
||||||
|
data_dir,
|
||||||
|
create_client_on_request: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,10 @@ impl<'a> StorageTxn for InnerTxn<'a> {
|
|||||||
Ok(self.0.clients.get(&client_id).cloned())
|
Ok(self.0.clients.get(&client_id).cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn list_clients(&mut self) -> anyhow::Result<Vec<Uuid>> {
|
||||||
|
Ok(self.0.clients.keys().map(|key| key.clone()).collect())
|
||||||
|
}
|
||||||
|
|
||||||
fn new_client(&mut self, client_id: Uuid, latest_version_id: Uuid) -> anyhow::Result<()> {
|
fn new_client(&mut self, client_id: Uuid, latest_version_id: Uuid) -> anyhow::Result<()> {
|
||||||
if self.0.clients.get(&client_id).is_some() {
|
if self.0.clients.get(&client_id).is_some() {
|
||||||
return Err(anyhow::anyhow!("Client {} already exists", client_id));
|
return Err(anyhow::anyhow!("Client {} already exists", client_id));
|
||||||
|
@ -41,6 +41,9 @@ pub trait StorageTxn {
|
|||||||
/// Get information about the given client
|
/// Get information about the given client
|
||||||
fn get_client(&mut self, client_id: Uuid) -> anyhow::Result<Option<Client>>;
|
fn get_client(&mut self, client_id: Uuid) -> anyhow::Result<Option<Client>>;
|
||||||
|
|
||||||
|
/// Get information about the given client
|
||||||
|
fn list_clients(&mut self) -> anyhow::Result<Vec<Uuid>>;
|
||||||
|
|
||||||
/// Create a new client with the given latest_version_id
|
/// Create a new client with the given latest_version_id
|
||||||
fn new_client(&mut self, client_id: Uuid, latest_version_id: Uuid) -> anyhow::Result<()>;
|
fn new_client(&mut self, client_id: Uuid, latest_version_id: Uuid) -> anyhow::Result<()>;
|
||||||
|
|
||||||
|
@ -166,6 +166,22 @@ impl StorageTxn for Txn {
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn list_clients(&mut self) -> anyhow::Result<Vec<Uuid>> {
|
||||||
|
let t = self.get_txn()?;
|
||||||
|
|
||||||
|
let mut stmt = t.prepare("SELECT client_id FROM clients")?;
|
||||||
|
let rows = stmt
|
||||||
|
.query_map([], |r| r.get::<usize, StoredUuid>(0))
|
||||||
|
.context("Error getting clients")?;
|
||||||
|
|
||||||
|
let mut result = Vec::new();
|
||||||
|
for client_id_result in rows {
|
||||||
|
result.push(client_id_result?.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
fn new_client(&mut self, client_id: Uuid, latest_version_id: Uuid) -> anyhow::Result<()> {
|
fn new_client(&mut self, client_id: Uuid, latest_version_id: Uuid) -> anyhow::Result<()> {
|
||||||
let t = self.get_txn()?;
|
let t = self.get_txn()?;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user