fix-blocks-cycle.md 1.9 KB

This document describes the handling of cycles formed between multiple blocks in the implementation of db-sync.

When cycles are detected

  • Cycles are detected on the server when applying client tx batches in deps/db-sync/src/logseq/db_sync/worker.cljs.
  • The server calls logseq.db-sync.cycle/detect-cycle which inspects updates to :block/parent (and other special attrs like class extends).
  • If applying the tx would introduce a cycle, the server rejects the batch with {:type "tx/reject" :reason "cycle" ...}.

What the server returns

  • The reject payload includes:
    • attr: the attribute that introduced the cycle (for blocks this is :block/parent).
    • server-values: a map of the affected entities to the server’s current value for attr (from logseq.db-sync.cycle/server-values-for).
  • This allows the client to realign its local state to the server’s authoritative values.

Client-side reconciliation

  • The client handles tx/reject with reason "cycle" in src/main/frontend/worker/db_sync.cljs.
  • It calls reconcile-cycle! which builds :db/add / :db/retract ops to restore attr to the server values, then transacts them locally with :rtc-tx? true.
  • The intent is to correct local cycles and prevent re-uploading conflicting changes.
  • The client also strips cycle-related attrs (:block/parent, :logseq.property.class/extends) from the rejected inflight txs, requeues the remaining changes, and flushes pending txs so other attribute updates still sync.
  • TODO: During pull/ok, after applying remote txs, the client checks cycle-related attrs touched by the tx. If a cycle is detected:
    • For :block/parent, reparent the affected block to its page root (top-level) and persist the op so it is uploaded to the server.
    • For other cycle attrs (e.g. :logseq.property.class/extends), retract the attr locally.

Known pitfalls and fixes

  • :logseq.property.class/extends not well handled yet, let it be for now, FIX it later