Skip to content

Settings sync: sync engine with revision conflict handling #986

Closed

Description

@enaboapps

Part of cross-device settings sync for Switchify PC.

Scope

  • Download on sign-in and app start. Upload 3 s after any settings save, waiting until changes stop.
  • Avoid lost writes with revision checks: PATCH ...?revision=eq.N, and if no row matches, download again and resolve.
  • On first sign-in, if both this PC and the cloud have customised settings, ask whether to keep this PC's settings or use the cloud copy. Never overwrite silently.
  • Keep working offline, retry with backoff, and show sync status in the UI.
  • Never log the contents of the settings document.

Acceptance

  • Tests against a fake back end covering conflicts, offline retry, the first-sign-in prompt and sign-out.

Activity

  1. added this to the v1.0.0-rc.22 milestone on Oct 5, 2026
  2. enaboapps commented on Oct 5, 2026

    @enaboapps
    ContributorAuthor

    Notes from the Supabase review (switchifyapp/switchify-supabase#2), for the client contract:

    • Create the row with a plain POST. A 409/23505 means another device created it first; fall back to GET then PATCH.
    • Update with PATCH ?revision=eq.N and Prefer: return=representation. An empty result means a conflict.
    • Never upsert (merge-duplicates / on_conflict), because an upsert bypasses the revision check. Clients have no DELETE permission.
    • Key the cached revision and last-synced document by user_id. After an account is deleted and recreated, the new row starts at revision 1 under a new uid, so a cache from the old account must never be applied to the new one.
    • The 256 KiB payload limit is measured on jsonb storage size, so treat it as approximate and keep the document well under it.
  3. enaboapps commented on Oct 5, 2026

    @enaboapps
    ContributorAuthor

    Notes from the #989 review, for the sync engine:

    • Call portable_settings::apply on the main thread (run_on_main_thread, like configure_point_scan).
    • apply can partly succeed, for example when a file write fails or a switch capture is active. Treat an error as retryable: re-running it with the same document converges.
    • Profile changes aren't part of AppState, so emit_state won't refresh the Profiles screen. Emit a profiles-changed event, or have the UI refetch list_switch_profiles, after a sync applies profiles.
    • ParseError::Newer means the cloud copy came from a newer app. Show the "update Switchify PC" message and don't upload over it.
  4. enaboapps commented on Oct 5, 2026

    @enaboapps
    ContributorAuthor

    One more note from the #989 review: parsing requires an exact JSON round trip, and the document contains explicit nulls. Never strip nulls on the way to or from storage (no jsonb_strip_nulls, and no client that drops null fields), or every document will fail to parse. Add a test that round-trips through the real column.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions