aboutsummaryrefslogtreecommitdiffstats
path: root/crates/atuin-daemon/src/server/sync.rs
diff options
context:
space:
mode:
authorEllie Huxtable <ellie@elliehuxtable.com>2024-05-08 12:09:04 +0100
committerGitHub <noreply@github.com>2024-05-08 12:09:04 +0100
commitbce0faa1c2dc221b0ff77d2cd647bfb2a48ffa7e (patch)
tree4d66bd95b151d3bab4cabf8799805c739f608bc4 /crates/atuin-daemon/src/server/sync.rs
parentfix(config): add quotes for strategy value in comment (#1993) (diff)
downloadatuin-bce0faa1c2dc221b0ff77d2cd647bfb2a48ffa7e.zip
feat: add background daemon (#2006)
* init daemon crate * wip * minimal functioning daemon, needs cleanup for sure * better errors * add signal cleanup * logging * things * add sync worker * move daemon crate * 30s -> 5mins * make clippy happy * fix stuff maybe? * fmt * trim packages * rate limit fix * more protoc huh * this makes no sense, why linux why * can it install literally just curl * windows in ci is slow, and all the newer things will not work there. disable the daemon feature and it will build * add daemon feature * maybe this * ok wut where is protoc * try setting protoc * hm * try copying protoc * remove optional * add cross config * idk nix * does nix want this? * some random pkg I found does this * uh oh * hack, be gone! * update contributing
Diffstat (limited to 'crates/atuin-daemon/src/server/sync.rs')
-rw-r--r--crates/atuin-daemon/src/server/sync.rs55
1 files changed, 55 insertions, 0 deletions
diff --git a/crates/atuin-daemon/src/server/sync.rs b/crates/atuin-daemon/src/server/sync.rs
new file mode 100644
index 00000000..de34779c
--- /dev/null
+++ b/crates/atuin-daemon/src/server/sync.rs
@@ -0,0 +1,55 @@
+use eyre::Result;
+use rand::Rng;
+use tokio::time::{self, MissedTickBehavior};
+
+use atuin_client::{
+ record::{sqlite_store::SqliteStore, sync},
+ settings::Settings,
+};
+
+pub async fn worker(settings: Settings, store: SqliteStore) -> Result<()> {
+ tracing::info!("booting sync worker");
+
+ let mut ticker = time::interval(time::Duration::from_secs(settings.daemon.sync_frequency));
+
+ // IMPORTANT: without this, if we miss ticks because a sync takes ages or is otherwise delayed,
+ // we may end up running a lot of syncs in a hot loop. No bueno!
+ ticker.set_missed_tick_behavior(MissedTickBehavior::Skip);
+
+ loop {
+ ticker.tick().await;
+ tracing::info!("sync worker tick");
+
+ let res = sync::sync(&settings, &store).await;
+
+ if let Err(e) = res {
+ tracing::error!("sync tick failed with {e}");
+ let mut rng = rand::thread_rng();
+
+ let new_interval = ticker.period().as_secs_f64() * rng.gen_range(2.0..2.2);
+
+ // Don't backoff by more than 30 mins
+ if new_interval > 60.0 * 30.0 {
+ continue;
+ }
+
+ ticker = time::interval(time::Duration::from_secs(new_interval as u64));
+ ticker.reset_after(time::Duration::from_secs(new_interval as u64));
+
+ tracing::error!("backing off, next sync tick in {new_interval}");
+ } else {
+ let (uploaded, downloaded) = res.unwrap();
+
+ tracing::info!(
+ uploaded = ?uploaded,
+ downloaded = ?downloaded,
+ "sync complete"
+ );
+
+ // Reset backoff on success
+ if ticker.period().as_secs() != settings.daemon.sync_frequency {
+ ticker = time::interval(time::Duration::from_secs(settings.daemon.sync_frequency));
+ }
+ }
+ }
+}