Skip to content

Commit

Permalink
fix(sync): improve error handling in daemon and add exponential backo…
Browse files Browse the repository at this point in the history
…ff for server connection

- Added error logging in daemon before re-throwing errors
- Implemented exponential backoff when checking if the server is running
- Addresses issue ActivityWatch/aw-qt#105
  • Loading branch information
ErikBjare committed Oct 17, 2024
1 parent 656f3c9 commit 9b0d59f
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 10 deletions.
22 changes: 16 additions & 6 deletions aw-sync/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// Start daemon
Commands::Daemon {} => {
info!("Starting daemon...");
// TODO: log any errors before re-throwing
daemon(&client)?;
}
// Perform basic sync
Expand Down Expand Up @@ -208,14 +209,23 @@ fn main() -> Result<(), Box<dyn Error>> {

fn daemon(client: &AwClient) -> Result<(), Box<dyn Error>> {
loop {
info!("Pulling from all hosts");
sync_wrapper::pull_all(client)?;

info!("Pushing local data");
sync_wrapper::push(client)?;
if let Err(e) = daemon_sync_cycle(client) {
error!("Error during sync cycle: {}", e);
// Re-throw the error
return Err(e);
}

info!("Sync pass done, sleeping for 5 minutes");

std::thread::sleep(std::time::Duration::from_secs(300));
}
}

fn daemon_sync_cycle(client: &AwClient) -> Result<(), Box<dyn Error>> {
info!("Pulling from all hosts");
sync_wrapper::pull_all(client)?;

info!("Pushing local data");
sync_wrapper::push(client)?;

Ok(())
}
34 changes: 30 additions & 4 deletions aw-sync/src/sync_wrapper.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::error::Error;
use std::fs;
use std::net::TcpStream;
use std::time::Duration;

use crate::sync::{sync_run, SyncMode, SyncSpec};
use aw_client_rust::blocking::AwClient;
Expand All @@ -13,16 +14,41 @@ pub fn pull_all(client: &AwClient) -> Result<(), Box<dyn Error>> {
Ok(())
}

fn wait_for_server(socket_addr: &std::net::SocketAddr) -> Result<(), Box<dyn Error>> {
// Check if server is running with exponential backoff
let mut retry_delay = Duration::from_millis(100);
let max_retry_delay = Duration::from_secs(10);
let mut total_wait = Duration::from_secs(0);

while total_wait < max_retry_delay {
match TcpStream::connect_timeout(socket_addr, retry_delay) {
Ok(_) => break,
Err(_) => {
std::thread::sleep(retry_delay);
total_wait += retry_delay;
retry_delay = std::cmp::min(retry_delay * 2, max_retry_delay);
}
}
}

if total_wait >= max_retry_delay {
return Err(format!(
"Local server {} not running after 10 seconds of retrying",
socket_addr
)
.into());
}

Ok(())
}

pub fn pull(host: &str, client: &AwClient) -> Result<(), Box<dyn Error>> {
let socket_addrs = client.baseurl.socket_addrs(|| None)?;
let socket_addr = socket_addrs
.get(0)
.ok_or("Unable to resolve baseurl into socket address")?;

// Check if server is running
if TcpStream::connect(socket_addr).is_err() {
return Err(format!("Local server {} not running", &client.baseurl).into());
}
wait_for_server(socket_addr)?;

// Path to the sync folder
// Sync folder is structured ./{hostname}/{device_id}/test.db
Expand Down

0 comments on commit 9b0d59f

Please sign in to comment.