Skip to content

Commit 72dead7

Browse files
authored
fix(sync): re-arm a recovery probe that died while offline (closes #207) (#212)
* fix(sync): re-arm a recovery probe that died while offline (closes #207) * chore(release): bump version to 0.2.24 --------- Co-authored-by: gnacho <hnacho@proton.me>
1 parent 8b165fb commit 72dead7

10 files changed

Lines changed: 72 additions & 13 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
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).
44

5+
## [0.2.24] - 2026-09-17
6+
7+
### Fixed
8+
9+
- 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).
10+
511
## [0.2.22] - 2026-09-17
612

713
### Fixed

‎Cargo.lock‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "nextsync"
3-
version = "0.2.22"
3+
version = "0.2.24"
44
edition = "2021"
55
rust-version = "1.83"
66
license = "GPL-3.0-or-later"

‎PKGBUILD‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Maintainer: gnacho <https://github.com/gnacho>
22
pkgname=nextsync
3-
pkgver=0.2.22
3+
pkgver=0.2.24
44
pkgrel=1
55
pkgdesc='Nextcloud desktop synchronization client for GNOME (Rust rewrite)'
66
arch=('x86_64' 'aarch64')

‎README.es.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
</p>
1818
<p>
1919
<a href="https://github.com/gnacho/nextsync/actions/workflows/ci.yml"><img src="https://github.com/gnacho/nextsync/actions/workflows/ci.yml/badge.svg" alt="Estado de CI"></a>
20-
<img src="https://img.shields.io/badge/version-0.2.22-blue?style=flat-square" alt="Versión 0.2.22">
20+
<img src="https://img.shields.io/badge/version-0.2.24-blue?style=flat-square" alt="Versión 0.2.24">
2121
<img src="https://img.shields.io/badge/license-GPL--3.0%2B-informational?style=flat-square" alt="GNU GPL v3 o posterior">
2222
</p>
2323
</div>
@@ -84,7 +84,7 @@ Ambos motores se esconden detrás del mismo trait pequeño, así que un proveedo
8484
Descarga el `.pkg.tar.zst` de la [última release](https://github.com/gnacho/nextsync/releases/latest) e instálalo:
8585

8686
```bash
87-
sudo pacman -U nextsync-0.2.22-1-x86_64.pkg.tar.zst
87+
sudo pacman -U nextsync-0.2.24-1-x86_64.pkg.tar.zst
8888
```
8989

9090
El paquete depende de `gtk4` y `libadwaita`. Para cuentas Nextcloud instala `nextcloud-client` (aporta `nextcloudcmd`); para cuentas OpenCloud, el `opencloudcmd` oficial.

‎README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
</p>
1818
<p>
1919
<a href="https://github.com/gnacho/nextsync/actions/workflows/ci.yml"><img src="https://github.com/gnacho/nextsync/actions/workflows/ci.yml/badge.svg" alt="CI status"></a>
20-
<img src="https://img.shields.io/badge/version-0.2.22-blue?style=flat-square" alt="Version 0.2.22">
20+
<img src="https://img.shields.io/badge/version-0.2.24-blue?style=flat-square" alt="Version 0.2.24">
2121
<img src="https://img.shields.io/badge/license-GPL--3.0%2B-informational?style=flat-square" alt="GNU GPL v3 or later">
2222
</p>
2323
</div>
@@ -84,7 +84,7 @@ Both engines sit behind the same small trait, so a new provider is a command bui
8484
Download the `.pkg.tar.zst` from the [latest release](https://github.com/gnacho/nextsync/releases/latest) and install it:
8585

8686
```bash
87-
sudo pacman -U nextsync-0.2.22-1-x86_64.pkg.tar.zst
87+
sudo pacman -U nextsync-0.2.24-1-x86_64.pkg.tar.zst
8888
```
8989

9090
The package depends on `gtk4` and `libadwaita`. For Nextcloud accounts install `nextcloud-client` (it provides `nextcloudcmd`); for OpenCloud accounts, the official `opencloudcmd`.

‎data/io.github.gnacho.nextsync.metainfo.xml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<icon type="stock">io.github.gnacho.nextsync</icon>
3333
<content_rating type="oars-1.1"/>
3434
<releases>
35+
<release version="0.2.24" date="2026-09-17"/>
3536
<release version="0.2.22" date="2026-09-17"/>
3637
<release version="0.2.20" date="2026-09-08"/>
3738
<release version="0.2.18" date="2026-09-08"/>

‎landing/index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ <h3 data-i18n="compare.ht">Lo que NextSync no hace (todavía)</h3>
210210
<h2 class="reveal" data-i18n="install.title">Instalación fácil y rápida</h2>
211211
<p class="lead reveal" data-i18n="install.lead">En Arch, CachyOS y derivadas hay paquete listo en cada release.</p>
212212
<div class="card install-card reveal">
213-
<pre class="code-block"><code id="installCmd">sudo pacman -U nextsync-0.2.22-1-x86_64.pkg.tar.zst</code></pre>
213+
<pre class="code-block"><code id="installCmd">sudo pacman -U nextsync-0.2.24-1-x86_64.pkg.tar.zst</code></pre>
214214
<button class="btn suggested" id="copyBtn" data-i18n="install.copy">Copiar comando</button>
215215
<p class="small-print" data-i18n="install.note">Descarga el paquete <code>.pkg.tar.zst</code> más reciente desde <a href="https://github.com/gnacho/nextsync/releases" target="_blank" rel="noopener">GitHub Releases</a> y ajusta el nombre del fichero.</p>
216216
</div>

‎src/core/scheduler.rs‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,16 @@ impl SchedulerInner {
11921192
self.state
11931193
.set(AppState::Offline, t("Waiting for a network connection"));
11941194
} else if !was_online {
1195+
// Issue #207: the recovery probe is a one-shot timer; if it fired
1196+
// while the machine was offline, `start` aborted on !online and
1197+
// the timer died. Re-arm it now so the folder recovers by itself
1198+
// once the network is back, instead of sitting queued behind the
1199+
// server_unreachable gate until a manual sync. The probe guard
1200+
// (start_source) makes the re-arm a no-op if one is still pending.
1201+
if self.server_unreachable {
1202+
self.queue.add(Trigger::Retry);
1203+
self.schedule_server_probe();
1204+
}
11951205
if !self.queue.is_empty() || !self.manual_only() {
11961206
self.request(Trigger::NetworkRestored);
11971207
} else {
@@ -1777,6 +1787,49 @@ mod tests {
17771787
assert_eq!(scheduler.state().snapshot().state, AppState::IdleOk);
17781788
}
17791789

1790+
/// Issue #207: the recovery probe is a one-shot timer. If it fires while
1791+
/// the machine is offline, `start` aborts on !online and the timer is
1792+
/// gone for good. When the network comes back, the folder must still
1793+
/// recover on its own - the probe is re-armed and the queued retry runs -
1794+
/// without a manual sync or an app restart.
1795+
#[test]
1796+
fn network_restore_rearms_a_probe_that_died_while_offline() {
1797+
let (scheduler, source, runner) = make_scheduler(None);
1798+
scheduler.request(Trigger::Startup);
1799+
run_idle(&source);
1800+
finish(&runner, SyncOutcome::NetworkError);
1801+
assert!(scheduler.server_unreachable());
1802+
let probe_id = source.borrow().only_id();
1803+
1804+
// Connectivity drops before the probe fires; the probe fires anyway
1805+
// and its one-shot start() aborts on !online: the timer is dead.
1806+
scheduler.set_online(false);
1807+
fire_timer(&source, probe_id);
1808+
assert_eq!(
1809+
runner.0.borrow().start_calls,
1810+
1,
1811+
"an offline probe must not run the engine"
1812+
);
1813+
assert_eq!(
1814+
source.borrow().pending(),
1815+
0,
1816+
"the one-shot probe timer is gone"
1817+
);
1818+
1819+
// Connectivity returns: the folder recovers without a manual sync.
1820+
scheduler.set_online(true);
1821+
assert!(
1822+
source.borrow().pending() >= 1,
1823+
"the recovery probe is re-armed on network restore"
1824+
);
1825+
let rearmed_id = source.borrow().only_id();
1826+
fire_timer(&source, rearmed_id);
1827+
assert_eq!(runner.0.borrow().start_calls, 2);
1828+
finish(&runner, SyncOutcome::Success);
1829+
assert!(!scheduler.server_unreachable());
1830+
assert_eq!(scheduler.state().snapshot().state, AppState::IdleOk);
1831+
}
1832+
17801833
/// Issue #179: after the server recovers (Success clears the gate), a
17811834
/// fresh automatic trigger runs the engine again.
17821835
#[test]

‎version.json‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
{
22
"schema_version": 1,
3-
"version": "0.2.22",
3+
"version": "0.2.24",
44
"mandatory": false,
5-
"summary": "Detect a missing sync engine and stop reporting success when nothing can be synchronized.",
5+
"summary": "Folders recover on their own after connectivity returns, even when the recovery probe fired while the machine was offline.",
66
"changelog": [
7-
"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.",
8-
"A configured engine path that no longer exists resolves as missing too, so a stale override surfaces the same actionable state.",
9-
"The missing-engine reason is written to the daily log and raises a desktop notification like other problem outcomes."
7+
"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.",
8+
"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."
109
],
1110
"released_at": "2026-09-17T00:00:00Z"
1211
}

0 commit comments

Comments
 (0)