Zum Inhalt springen

Sync protocol

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

The sync protocol is a simple incremental pull plus a conflict-aware push. The server is the source of truth; the client carries a per-device cursor and reconciles based on UpdatedAt timestamps.

MethodPathPurpose
GET/api/sync/pull?since={ISO8601}Incremental pull of records updated since the given timestamp
POST/api/sync/pushPush client changes; receive server-assigned IDs and conflicts
GET/api/sync/statusCurrent sync cursor, last successful sync, queue depth
GET/api/sync/eventsAudit trail of recent sync activity
GET/api/sync/quotaCurrent usage vs. caps

All require a JWT. The sync rate-limit policy (30 req/min per user) is applied to push and pull.

The client sends its last-known sync timestamp and receives a SyncPullResponse:

{
"templates": [...],
"providers": [...],
"sessions": [...],
"memories": [...],
"todos": [...],
"settings": { ... },
"serverTime": "2026-05-03T12:34:56Z"
}

The client persists serverTime as its new cursor. If since is omitted (first sync), the response contains the full set of records the user owns.

The client batches local changes into a SyncPushRequest and sends them in one shot:

{
"templates": [...],
"providers": [...],
"sessions": [...],
"memories": [...],
"todos": [...],
"settings": { ... }
}

The server applies validation (16 unique rules — max field lengths, required fields, format checks), then walks the request:

  1. Quota checkQuotaService.CheckQuotaAsync aborts the entire push with 409 quota_exceeded if any cap would be violated.
  2. Conflict resolutionConflictResolver compares server UpdatedAt with the client-provided value:
    • Default: last-write-wins (later timestamp wins).
    • Server-wins: applied to auth-sensitive data.
  3. Persist — successful records are written inside a single EF transaction.

The SyncPushResponse contains:

  • Server-assigned IDs for new records.
  • A conflicts array describing per-record decisions (so the client can update its local view).
  • A new serverTime cursor.

A push that fails validation returns 400 with an errors array; nothing is persisted. The client should surface the errors and retry after the user fixes them.

SyncCursor rows are per-device, not per-user. This lets a single user run multiple devices that move at independent speeds without one device’s late writes pulling another back. The DeviceId is read from the X-Pia-Device-Id header, populated by the desktop client.