Skip to content

sync: a deterministically unreadable relation row wedges a resource forever #568

Description

@DouglasdeMoura

Problem

exportResourceFor aborts the push when hydration fails (2f38ea4, ff4c2c9),
because a partially populated record PUT to the server overwrites the complete
copy there — alarms and attendees silently deleted for every other client.

That is right for a transient failure: the dirty flag stays set and the next
sync retries the whole resource. It has no answer for a deterministic one. If
one relation row fails to scan every single time — a NULL in a column
scan_helpers.go reads as a non-pointer after a hand-edited database or a
partially applied migration — then:

  • every sync re-attempts that resource and fails identically,
  • the resource stays dirty forever,
  • the calendar shows a permanent sync-failure warning (the ⚠ sidebar glyph),
  • and no other edit to that event ever reaches the server.

There is no path to convergence short of hand-editing the database, and nothing
tells the user that is what is required.

Why this was not just fixed

The obvious "fix" — give up and push anyway — is exactly the data loss 2f38ea4
was written to prevent. Failing loudly on unreadable local data is the correct
default. What is missing is not tolerance, it is a way out.

Proposed direction

Some combination of:

  1. Attempt tracking. Record consecutive push failures per sync_resource.
    After N identical failures, stop retrying every cycle (back off), so one
    wedged resource does not make every sync report an error.
  2. A diagnosable message. The error should say which relation failed and
    that the resource is stuck, not just hydrate event uid ....
  3. An escape hatch. Something like chroncal sync doctor that lists wedged
    resources and offers to push without the unreadable relation after
    explicit confirmation
    — the user accepting the loss knowingly is very
    different from us doing it silently.

(3) is the part that actually resolves the finding; (1) and (2) make it bearable
in the meantime.

Context

Found by code review of 781e70b^..HEAD, verdict PLAUSIBLE. Deliberately not
fixed in that round because every quick fix reintroduces silent amputation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions