sync

package
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 26, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package sync holds the offline synchronisation context's own entities (offline-sync.md §10): what the server keeps about the devices that synchronise, beside the change log they read.

Index

Constants

View Source
const (
	PlatformMaxLength    = 40
	DisplayNameMaxLength = 120
)

The bounds of what a device says about itself (api/openapi.yaml, SyncPullRequest).

Variables

This section is empty.

Functions

func Bound

func Bound(reading shared.HLC, serverNow time.Time, skew time.Duration) (shared.HLC, time.Duration)

Bound applies §4.1's rule to a device's clock reading: a reading further than the permitted skew from server time is replaced by a server reading, and the caller is told by how much it was out so that the fact can be logged - the device and the drift, never the content.

Both directions are bounded. A device ahead of the server would outvote everybody for as long as its lead lasted; a device behind would lose every merge it should have won, which is quieter and just as wrong. The replacement keeps the device's identifier: the reading is still the device's act, only its moment is the server's.

Types

type Contact

type Contact struct {
	DeviceID     shared.ID
	AccountID    shared.ID
	CredentialID shared.ID
	// Platform and DisplayName are optional: empty leaves what the row holds.
	Platform    string
	DisplayName string
	// LastSeq is the position after the page, zero when the contact did not finish one.
	LastSeq int64
	Now     time.Time
}

Contact is what one pull or push says about the device making it.

func (Contact) Validate

func (c Contact) Validate() (Contact, error)

Validate bounds what a client says about its device, and normalises it: trimmed, and refused when longer than the contract allows. The identifier is required and has to be one the client minted - a UUIDv7 - because it is what every change of the device is later attributed to (offline-sync.md §9, requirement 1).

type Device

type Device struct {
	ID        shared.ID
	TenantID  shared.ID
	AccountID shared.ID
	// Platform and DisplayName are what the device said about itself, last value standing. Both
	// are personal data - a name somebody typed, a class of machine they own - and travel to the
	// device list and nowhere else (rule 10).
	Platform    string
	DisplayName string
	// LastSeq is where the device last stood in the log: the position of the last page it
	// pulled. Zero for a device that has never finished a page.
	LastSeq    int64
	LastSeenAt time.Time
	CreatedAt  time.Time
	// Blocked is a forgotten device: every contact from the identifier is refused until the
	// sweep removes the row and the client mints a new identifier. The row stays rather than
	// going at once, so that the list shows what a person ended and so that an identifier cannot
	// register afresh while somebody still holds the old one.
	Blocked bool
	// CredentialID is the credential of the request that last touched the device - a session,
	// for a client that signed in; a token's identifier for one that did not. Forgetting the
	// device revokes it where it is a session and does nothing where it is not (migration 0082).
	CredentialID shared.ID
}

Device is one installation of a client on one machine, registered to one account (offline-sync.md §6, §10). The identifier is the client's - minted once, kept in its own store, sent with every pull and push - and it is what a push's `op_id`s and a change's `device_id` name.

type MutationKind

type MutationKind string

MutationKind is what a device did offline, in the contract's words (api/openapi.yaml, SyncMutation.kind).

const (
	ItemCreate MutationKind = "ITEM_CREATE"
	ItemPatch  MutationKind = "ITEM_PATCH"
	ItemDelete MutationKind = "ITEM_DELETE"
	SetAdd     MutationKind = "SET_ADD"
	SetRemove  MutationKind = "SET_REMOVE"
	Move       MutationKind = "MOVE"
	CommentAdd MutationKind = "COMMENT_ADD"
)

func MutationKinds

func MutationKinds() []MutationKind

MutationKinds is the closed set, in the contract's order.

func (MutationKind) Valid

func (k MutationKind) Valid() bool

Valid reports whether the kind is one the contract names.

type ResultKind

type ResultKind string

ResultKind is what became of one mutation (offline-sync.md §3.2).

const (
	// Applied: every field the device sent won, and nothing else had moved since its base.
	Applied ResultKind = "APPLIED"
	// Merged: the server's copy had moved; some of what the device sent won and some lost, and
	// the result carries the server's state so the device adopts it.
	Merged ResultKind = "MERGED"
	// Rejected: the mutation could not be applied at all - the use case refused it, the entry is
	// gone, the device may not - and the result carries the code.
	Rejected ResultKind = "REJECTED"
	// Conflict: a free-text field lost, and the displaced version is preserved as a comment; the
	// result carries both values so a client can offer the choice (offline-sync.md §5).
	Conflict ResultKind = "CONFLICT"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL