Skip to content

Official-client parity: file-id routing, failure backoff, push-aware intervals, heartbeat (#183 #184 #185 #186) - #188

Merged
gnacho merged 2 commits into
mainfrom
feat/183-186-file-ids-backoff-heartbeat
Aug 26, 2026
Merged

gnacho merged 2 commits into
mainfrom
feat/183-186-file-ids-backoff-heartbeat

Conversation

@gnacho

@gnacho gnacho commented Aug 26, 2026

Copy link
Copy Markdown
Owner

Benchmarked against the official Nextcloud desktop client (nextcloud/desktop) and ported four robustness/performance improvements. Closes #183, #184, #185, #186.

#183 — Resolve notify_file_id and sync only the affected folder

The push client treated every notify_file_id <id> as a generic change and fanned out RemotePush to every folder of the account. The official client resolves the id against its folder journal (SyncJournalDb::hasFileIds) and schedules only the folder that owns the file.

  • push.rs: opt in to listen n_id after authenticated; parse notify_file_id <json-array> into file ids (FileNotification(Vec<i64>)); a legacy notify_file keeps an empty list.
  • New core/files_journal.rs: read-only lookup of the external engine's .sync_*.db journal (the same journal nextcloudcmd keeps), answering whether a folder knows any notified id (metadata.fileid compared via CAST(... AS INTEGER)).
  • Scheduler::has_file_ids + apply_remote_push: route the hint to only the folders that contain the file; empty ids (legacy) still fan out.

#184 — Per-folder consecutive-failure backoff (10/30/60s)

The official client delays the next run by 10s/30s/60s depending on consecutiveFailingSyncs. Ours re-ran on every trigger.

  • consecutive_failing_syncs counter on the scheduler (reset on success/conflict, incremented on failure).
  • failure_backoff_seconds() (10/30/60) + schedule_after(): cooldown_finished backs off instead of re-running immediately once 3+ consecutive failures accrue.

#185 — Skip remote-interval polling while push is active

slotEtagPollTimerTimeout in the official client only polls accounts whose push is not ready. Ours armed RemoteInterval regardless.

  • remote_push_ready flag on the scheduler (set_remote_push_ready), wired from store_push_state: when the account's push is Connected, a RemoteInterval trigger is dropped.

#186 — WebSocket heartbeat + capped auth retries

The official client sends a 30s ping, detects a missing pong within its timeout, and caps auth attempts at 3.

  • push.rs: track last_activity in the worker loop; a connection with no inbound text/ping/pong for PUSH_HEARTBEAT_TIMEOUT_MS (75s) is torn down and reconnects (no silent zombie).
  • Cap consecutive failed auth attempts at MAX_PUSH_AUTH_ATTEMPTS (3); once exhausted the channel parks in AuthRequired instead of reconnecting in a loop. The streak resets on Authenticated and on coming back online.

Testing

685 tests (added 8), clippy clean, fmt applied.

New tests cover notify_file_id parsing, journal file-id membership, the failure-backoff table, and dropping RemoteInterval while push is ready.

@gnacho
gnacho merged commit 4150fb9 into main Aug 26, 2026
2 checks passed
@gnacho
gnacho deleted the feat/183-186-file-ids-backoff-heartbeat branch August 26, 2026 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resolve notify_file_id and sync only the affected folder (like the official client)

1 participant