From 281db6cd0b5379cc164f586a7eb3a657edbd52b0 Mon Sep 17 00:00:00 2001 From: gnacho Date: Thu, 17 Sep 2026 20:39:15 +0200 Subject: [PATCH 1/2] fix(sync): re-arm a recovery probe that died while offline (closes #207) --- src/core/scheduler.rs | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/core/scheduler.rs b/src/core/scheduler.rs index 03a4752..21255e6 100644 --- a/src/core/scheduler.rs +++ b/src/core/scheduler.rs @@ -1192,6 +1192,16 @@ impl SchedulerInner { self.state .set(AppState::Offline, t("Waiting for a network connection")); } else if !was_online { + // Issue #207: the recovery probe is a one-shot timer; if it fired + // while the machine was offline, `start` aborted on !online and + // the timer died. Re-arm it now so the folder recovers by itself + // once the network is back, instead of sitting queued behind the + // server_unreachable gate until a manual sync. The probe guard + // (start_source) makes the re-arm a no-op if one is still pending. + if self.server_unreachable { + self.queue.add(Trigger::Retry); + self.schedule_server_probe(); + } if !self.queue.is_empty() || !self.manual_only() { self.request(Trigger::NetworkRestored); } else { @@ -1777,6 +1787,49 @@ mod tests { assert_eq!(scheduler.state().snapshot().state, AppState::IdleOk); } + /// Issue #207: the recovery probe is a one-shot timer. If it fires while + /// the machine is offline, `start` aborts on !online and the timer is + /// gone for good. When the network comes back, the folder must still + /// recover on its own - the probe is re-armed and the queued retry runs - + /// without a manual sync or an app restart. + #[test] + fn network_restore_rearms_a_probe_that_died_while_offline() { + let (scheduler, source, runner) = make_scheduler(None); + scheduler.request(Trigger::Startup); + run_idle(&source); + finish(&runner, SyncOutcome::NetworkError); + assert!(scheduler.server_unreachable()); + let probe_id = source.borrow().only_id(); + + // Connectivity drops before the probe fires; the probe fires anyway + // and its one-shot start() aborts on !online: the timer is dead. + scheduler.set_online(false); + fire_timer(&source, probe_id); + assert_eq!( + runner.0.borrow().start_calls, + 1, + "an offline probe must not run the engine" + ); + assert_eq!( + source.borrow().pending(), + 0, + "the one-shot probe timer is gone" + ); + + // Connectivity returns: the folder recovers without a manual sync. + scheduler.set_online(true); + assert!( + source.borrow().pending() >= 1, + "the recovery probe is re-armed on network restore" + ); + let rearmed_id = source.borrow().only_id(); + fire_timer(&source, rearmed_id); + assert_eq!(runner.0.borrow().start_calls, 2); + finish(&runner, SyncOutcome::Success); + assert!(!scheduler.server_unreachable()); + assert_eq!(scheduler.state().snapshot().state, AppState::IdleOk); + } + /// Issue #179: after the server recovers (Success clears the gate), a /// fresh automatic trigger runs the engine again. #[test] From eb23e1c0c5939959c175cb195317b0668a44c1a9 Mon Sep 17 00:00:00 2001 From: gnacho Date: Thu, 17 Sep 2026 20:49:11 +0200 Subject: [PATCH 2/2] chore(release): bump version to 0.2.24 --- CHANGELOG.md | 6 ++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- PKGBUILD | 2 +- README.es.md | 4 ++-- README.md | 4 ++-- data/io.github.gnacho.nextsync.metainfo.xml | 1 + landing/index.html | 2 +- version.json | 9 ++++----- 9 files changed, 19 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35f8afd..2744f58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ Todas las versiones notables de NextSync se documentan aquí. El formato sigue [Keep a Changelog](https://keepachangelog.com/es/1.1.0/) y el versionado es **+0.0.2 por release, reiniciado en 0.1.4** (decisión del usuario, 22-Ago-2026; sustituye al +0.02 anterior). +## [0.2.24] - 2026-09-17 + +### Fixed + +- Folders no longer stay Offline after connectivity returns when the recovery probe fired while the machine was offline: the probe is re-armed on network restore and synchronization resumes on its own, without a manual sync or an app restart (#207). + ## [0.2.22] - 2026-09-17 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index 825a8df..61695f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1283,7 +1283,7 @@ dependencies = [ [[package]] name = "nextsync" -version = "0.2.22" +version = "0.2.24" dependencies = [ "async-channel", "data-encoding", diff --git a/Cargo.toml b/Cargo.toml index 785a7cd..97839d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nextsync" -version = "0.2.22" +version = "0.2.24" edition = "2021" rust-version = "1.83" license = "GPL-3.0-or-later" diff --git a/PKGBUILD b/PKGBUILD index 42efb6e..26f2199 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: gnacho pkgname=nextsync -pkgver=0.2.22 +pkgver=0.2.24 pkgrel=1 pkgdesc='Nextcloud desktop synchronization client for GNOME (Rust rewrite)' arch=('x86_64' 'aarch64') diff --git a/README.es.md b/README.es.md index 19f02a6..aad7e6d 100644 --- a/README.es.md +++ b/README.es.md @@ -17,7 +17,7 @@

Estado de CI - Versión 0.2.22 + Versión 0.2.24 GNU GPL v3 o posterior

@@ -84,7 +84,7 @@ Ambos motores se esconden detrás del mismo trait pequeño, así que un proveedo Descarga el `.pkg.tar.zst` de la [última release](https://github.com/gnacho/nextsync/releases/latest) e instálalo: ```bash -sudo pacman -U nextsync-0.2.22-1-x86_64.pkg.tar.zst +sudo pacman -U nextsync-0.2.24-1-x86_64.pkg.tar.zst ``` El paquete depende de `gtk4` y `libadwaita`. Para cuentas Nextcloud instala `nextcloud-client` (aporta `nextcloudcmd`); para cuentas OpenCloud, el `opencloudcmd` oficial. diff --git a/README.md b/README.md index 1d3a984..8cf5609 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@

CI status - Version 0.2.22 + Version 0.2.24 GNU GPL v3 or later

@@ -84,7 +84,7 @@ Both engines sit behind the same small trait, so a new provider is a command bui Download the `.pkg.tar.zst` from the [latest release](https://github.com/gnacho/nextsync/releases/latest) and install it: ```bash -sudo pacman -U nextsync-0.2.22-1-x86_64.pkg.tar.zst +sudo pacman -U nextsync-0.2.24-1-x86_64.pkg.tar.zst ``` The package depends on `gtk4` and `libadwaita`. For Nextcloud accounts install `nextcloud-client` (it provides `nextcloudcmd`); for OpenCloud accounts, the official `opencloudcmd`. diff --git a/data/io.github.gnacho.nextsync.metainfo.xml b/data/io.github.gnacho.nextsync.metainfo.xml index 99728ef..c5b1b1b 100644 --- a/data/io.github.gnacho.nextsync.metainfo.xml +++ b/data/io.github.gnacho.nextsync.metainfo.xml @@ -32,6 +32,7 @@ io.github.gnacho.nextsync + diff --git a/landing/index.html b/landing/index.html index bc09ba4..67e79e8 100644 --- a/landing/index.html +++ b/landing/index.html @@ -210,7 +210,7 @@

Lo que NextSync no hace (todavía)

Instalación fácil y rápida

En Arch, CachyOS y derivadas hay paquete listo en cada release.

-
sudo pacman -U nextsync-0.2.22-1-x86_64.pkg.tar.zst
+
sudo pacman -U nextsync-0.2.24-1-x86_64.pkg.tar.zst

Descarga el paquete .pkg.tar.zst más reciente desde GitHub Releases y ajusta el nombre del fichero.

diff --git a/version.json b/version.json index f512b8e..4a1bbf8 100644 --- a/version.json +++ b/version.json @@ -1,12 +1,11 @@ { "schema_version": 1, - "version": "0.2.22", + "version": "0.2.24", "mandatory": false, - "summary": "Detect a missing sync engine and stop reporting success when nothing can be synchronized.", + "summary": "Folders recover on their own after connectivity returns, even when the recovery probe fired while the machine was offline.", "changelog": [ - "When the sync binary (nextcloudcmd / opencloudcmd) is not installed, folders now show a clear 'sync engine is not installed' state instead of a generic failure - or worse, a misleading 'Synchronization completed' from the unchanged-ETag interval shortcut while nothing was actually synced.", - "A configured engine path that no longer exists resolves as missing too, so a stale override surfaces the same actionable state.", - "The missing-engine reason is written to the daily log and raises a desktop notification like other problem outcomes." + "After a period without connectivity, folders no longer stay Offline until a manual sync or an app restart: when the network comes back, the server recovery probe is re-armed automatically and synchronization resumes on its own.", + "Fixes the case where the one-shot recovery probe fired while the machine was offline, died silently, and the NetworkRestored trigger stayed parked behind the server-unreachable gate forever." ], "released_at": "2026-09-17T00:00:00Z" }