Skip to content

Conflict Resolution

In offline-first apps, conflicts are inevitable: multiple devices editing the same data while disconnected. Locorda resolves these using state-based CRDTs (Conflict-free Replicated Data Types) and merge contracts.

TODO: Document conflict scenarios with real examples from the implementation

Without automatic resolution, you’d need to:

  • Show conflict UI to users (poor UX)
  • Manually write merge logic (error-prone)
  • Accept data loss (one edit discarded)

Locorda uses state-based CRDTs to provide deterministic, automatic, conflict-free merge.

Locorda implements state-based CRDT algorithms for different property types:

@CrdtLwwRegister() - Last-Write-Wins Register

Section titled “@CrdtLwwRegister() - Last-Write-Wins Register”

TODO: Document:

  • Timestamp-based resolution
  • Causality tracking mechanism (if implemented)
  • Tie-breaking rules
  • Real examples from codebase

TODO: Document:

  • How additions and removals merge
  • Tombstone mechanism (if used)
  • Re-addition behavior
  • Real examples (e.g., tags on Note)

Immutable properties never change once set:

  • Creation timestamps
  • Identifying properties
  • Write-once data

TODO: Document behavior when conflicts occur on immutable fields

TODO: Document how property-level merging actually works in the implementation:

Each field is resolved independently using its CRDT strategy.

Real example from personal notes app:

@RootResource(appVocab, mergeContract: MergeContract())
class Note {
@RdfIriPart()
final String id;
@RdfProperty(Schema.name)
@CrdtLwwRegister()
final String title; // Resolved using LWW
@RdfProperty(Schema.keywords)
@CrdtOrSet()
final Set<String> tags; // Resolved using OR-Set
@RdfProperty(Schema.dateCreated)
@CrdtImmutable()
final DateTime createdAt; // Immutable
}

TODO: Add concrete merge scenario examples showing:

  • How timestamps work
  • Field-level resolution
  • Concurrent edits behavior

TODO: Document how the implementation handles truly concurrent edits:

  • Timestamp comparison mechanism
  • Tie-breaking rules (if any)
  • Node/device ID usage (if implemented)
  • Real-world examples

TODO: Document actual deletion behavior:

TODO: Verify and document:

  • Does Locorda use tombstones?
  • Deletion-wins vs edit-wins semantics
  • How deletion timestamps work
  • Garbage collection mechanism (if any)

TODO: Document if/how deleted resources can be recreated

TODO: Document how collections are actually handled:

Real example from personal notes app:

@RdfProperty(Schema.keywords)
@CrdtOrSet()
final Set<String> tags;

TODO: Document:

  • How OR-Set merge works
  • Addition/removal semantics
  • Re-addition behavior

TODO: Document list handling (if supported)

TODO: Document map handling (if supported)

TODO: Document actual edge cases from implementation:

TODO: How does the implementation handle clock skew?

  • Is there clock synchronization?
  • Mitigation strategies
  • Best practices

TODO: Document schema evolution support:

  • Adding new properties
  • Removing properties
  • Changing property types
  • Backward compatibility

RDF’s schema-flexible nature helps with evolution.

Real example from personal notes app:

@RdfUnmappedTriples(globalUnmapped: true)
final RdfGraph other;

TODO: Document:

  • How unmapped triples are preserved
  • Merge behavior for unmapped data
  • Round-tripping guarantees

TODO: Document theoretical properties:

TODO: Explain why Locorda’s CRDTs guarantee eventual consistency:

  • Commutativity
  • Associativity
  • Idempotency

TODO: Explain state-based vs operation-based CRDTs and why Locorda uses state-based

TODO: Document:

TODO: Provide real test examples from the codebase

TODO: Document logging and debugging tools

TODO: Document best practices based on real implementation experience:

  1. Choose appropriate CRDT strategies for each property
  2. Design for eventual consistency
  3. Test conflict scenarios
  4. TODO: Add more based on actual patterns

TODO: Summarize actual conflict resolution behavior:

  • State-based CRDTs provide automatic conflict resolution
  • @CrdtLwwRegister() for single-value properties
  • @CrdtOrSet() for multi-value properties (sets)
  • @CrdtImmutable() for write-once properties
  • Property-level merge using CRDT annotations
  • Deterministic convergence - all devices eventually agree

TODO: Add proper links once corresponding pages are created

  • 📘 Merge Contracts - Understand RootResource, SubResource, LocalResource
  • 📘 Architecture Overview - TODO
  • 📘 Testing Guide - TODO