Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion aw-sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ path = "src/main.rs"
log = "0.4"
toml = "0.8"
chrono = { version = "0.4", features = ["serde"] }
serde = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
reqwest = { version = "0.12", features = ["json", "blocking"] }
dirs = "6"
Expand Down
1 change: 1 addition & 0 deletions aw-sync/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ aw-sync daemon --mode pull
aw-sync sync --start-date "2024-01-01"

# Doctor: why is pull empty / which peers exist in the folder?
# Also prints the last persisted pass (peers, events, skips).
aw-sync status
```

Expand Down
53 changes: 25 additions & 28 deletions aw-sync/src/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,12 +274,9 @@ pub extern "C" fn Java_net_activitywatch_android_SyncInterface_syncPullAll(
jni_guard(&mut env, "syncPullAll", |env| {
let result: Result<String, String> = (|| {
let client = get_client(port)?;
pull_all(&client).map_err(|e| format!("Sync pull failed: {}", e))?;
Ok(json!({
"success": true,
"message": "Successfully pulled from all hosts"
})
.to_string())
let report = pull_all(&client).map_err(|e| format!("Sync pull failed: {}", e))?;
crate::report::persist_last_report_warn(&report);
Ok(report.to_jni_json())
})();
sync_result_to_jstring(env, "syncPullAll", result)
})
Expand All @@ -301,13 +298,10 @@ pub extern "C" fn Java_net_activitywatch_android_SyncInterface_syncPull(
.map_err(|e| format!("Failed to get hostname string: {}", e))?
.into();

pull(&hostname_str, &client).map_err(|e| format!("Sync pull failed: {}", e))?;

Ok(json!({
"success": true,
"message": format!("Successfully pulled from host: {}", hostname_str)
})
.to_string())
let report =
pull(&hostname_str, &client).map_err(|e| format!("Sync pull failed: {}", e))?;
crate::report::persist_last_report_warn(&report);
Ok(report.to_jni_json())
})();
sync_result_to_jstring(env, "syncPull", result)
})
Expand All @@ -328,13 +322,10 @@ pub extern "C" fn Java_net_activitywatch_android_SyncInterface_syncPush(
.map_err(|e| format!("Failed to get hostname: {}", e))?
.into();
let client = get_client(port)?;
push_with_hostname(&client, &hostname_str)
let report = push_with_hostname(&client, &hostname_str)
.map_err(|e| format!("Sync push failed: {}", e))?;
Ok(json!({
"success": true,
"message": "Successfully pushed local data"
})
.to_string())
crate::report::persist_last_report_warn(&report);
Ok(report.to_jni_json())
})();
sync_result_to_jstring(env, "syncPush", result)
})
Expand All @@ -356,16 +347,22 @@ pub extern "C" fn Java_net_activitywatch_android_SyncInterface_syncBoth(
.into();
let client = get_client(port)?;

pull_all(&client).map_err(|e| format!("Pull phase failed: {}", e))?;

push_with_hostname(&client, &hostname_str)
.map_err(|e| format!("Push phase failed: {}", e))?;
let mut report = pull_all(&client).map_err(|e| format!("Pull phase failed: {}", e))?;

Ok(json!({
"success": true,
"message": "Successfully completed full sync"
})
.to_string())
// Persist the pull result even if push fails, so the report on
// disk reflects the work the pass actually did.
match push_with_hostname(&client, &hostname_str) {
Ok(push_report) => report.merge(push_report),
Err(e) => {
report.record_push_failure(&e);
report.finish();
crate::report::persist_last_report_warn(&report);
return Err(format!("Push phase failed: {}", e));
}
}
report.finish();
crate::report::persist_last_report_warn(&report);
Ok(report.to_jni_json())
})();
sync_result_to_jstring(env, "syncBoth", result)
})
Expand Down
6 changes: 6 additions & 0 deletions aw-sync/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ extern crate chrono;
extern crate serde;
extern crate serde_json;

mod report;
pub use report::{
last_report_path, load_last_report, persist_last_report, persist_last_report_warn,
BucketReport, PeerOutcome, PeerReport, SyncMode, SyncReport,
};

mod sync;
pub use sync::create_datastore;
pub use sync::sync_datastores;
Expand Down
59 changes: 51 additions & 8 deletions aw-sync/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use aw_client_rust::blocking::AwClient;

mod accessmethod;
mod dirs;
mod report;
mod status;
mod sync;
mod sync_wrapper;
Expand Down Expand Up @@ -137,6 +138,7 @@ enum Commands {
///
/// 3-level peers come from the same `RemoteDb` walker `pull_all` uses;
/// 2-level leftovers and unrecognised entries sit on top of that list.
/// Also prints the last persisted `SyncReport` (what the previous pass did).
/// Does not create staging files.
Status {},
}
Expand Down Expand Up @@ -268,26 +270,57 @@ fn main() -> Result<(), Box<dyn Error>> {
start: start_date,
};

sync::sync_run(&client, &sync_spec, mode.unwrap_or(sync::SyncMode::Both))?
let report =
sync::sync_run(&client, &sync_spec, mode.unwrap_or(sync::SyncMode::Both))?;
info!("{}", report.summary_message());
aw_sync_persist(&report);
} else {
// Simple host-based sync mode (backwards compatibility)
let mut report = sync::SyncReport::new(sync::SyncMode::Both);
// Pull
match host {
Some(hosts) => {
for host in hosts.iter() {
info!("Pulling from host: {}", host);
sync_wrapper::pull(host, &client)?;
// A later host's `?` must not drop earlier hosts
// from last-sync-report.json. Same contract as the
// push-failure path below: persist the aggregate,
// then propagate.
match sync_wrapper::pull(host, &client) {
Ok(one) => report.merge(one),
Err(e) => {
report.record_pull_failure(host, &e);
report.finish();
info!("{}", report.summary_message());
aw_sync_persist(&report);
return Err(e);
}
}
}
}
None => {
info!("Pulling from all hosts");
sync_wrapper::pull_all(&client)?;
report.merge(sync_wrapper::pull_all(&client)?);
}
}

// Push
// Push. On failure the pull phase already did real work:
// persist what was pulled before propagating, so
// `aw-sync status` shows the pull, not just the push.
info!("Pushing local data");
sync_wrapper::push(&client)?
match sync_wrapper::push(&client) {
Ok(push_report) => report.merge(push_report),
Err(e) => {
report.record_push_failure(&e);
report.finish();
info!("{}", report.summary_message());
aw_sync_persist(&report);
return Err(e);
}
}
report.finish();
info!("{}", report.summary_message());
aw_sync_persist(&report);
}
}

Expand Down Expand Up @@ -337,9 +370,15 @@ fn daemon(
};

loop {
if let Err(e) = sync::sync_run(client, &sync_spec, mode) {
error!("Error during sync cycle: {}", e);
return Err(e);
match sync::sync_run(client, &sync_spec, mode) {
Ok(report) => {
info!("{}", report.summary_message());
aw_sync_persist(&report);
}
Err(e) => {
Comment thread
TimeToBuildBob marked this conversation as resolved.
error!("Error during sync cycle: {}", e);
return Err(e);
}
}

info!("Sync pass done, sleeping for 5 minutes");
Expand All @@ -357,3 +396,7 @@ fn daemon(

Ok(())
}

fn aw_sync_persist(report: &sync::SyncReport) {
crate::report::persist_last_report_warn(report);
}
Loading
Loading