Skip to main content

Module groups

Module groups 

Expand description

Where a version’s name lives: in the document, with the changes it names.

A name that lived in the widget would vanish on close, and a name that lived beside the document would never reach a collaborator. So a name is written into the same CRDT as the content it describes — one record at the document root per named range, keyed by the range it covers:

ROOT
  "tilo:group:<hex of the range's first change>"   <- the key IS the range
     label : "Intro rewrite"
     end   : "<hex of the range's last change>"   (absent while open)
     by    : "<actor hex of whoever wrote the name>"
     at    : <unix millis>

The key is the range’s first change, not minted per writer: two people naming the same run then collide on one map key, and automerge’s own conflict rule resolves it deterministically and identically on every peer (the loser stays reachable via get_conflicts). Records sit at the root rather than under one container map for the same reason at a coarser grain: a container created independently by two peers naming different ranges at the same time would have one discarded whole, silently losing a name. Flat, prefixed root keys have no container to race over.

Naming a version is a change like any other, but is deliberately not given its own row in the history surfaces — see is_group_marker.

Structs§

DisplayedSession
One work session beside a seam, as the person saw it: its named record, or None while it is still an automatic projection with these bounds and title.

Constants§

GROUPS_KEY
Namespaced so it cannot collide with an app’s own schema: tilo-doc uses content / comments / props, and the shell’s room document uses workspaces / active.
MAX_LABEL_LEN
A version name is a label, not a paragraph; past this it stops fitting anywhere it is rendered and starts being a way to make another user’s timeline unreadable.

Functions§

clear_name
Remove a name. The changes it covered stay; only the band goes.
close_range
Close an open range at end. false when no such record exists.
is_group_marker
True when every patch in patches lands inside the named-range map — used by the producer to keep naming out of the row list. An empty patch set is not a marker: a change that did nothing visible is still a change, and hiding it would be incorrect behaviour.
materialize_and_move_boundary
Correct a seam even when one or both work sessions are still automatic projections. Missing records are materialized with the titles and bounds the person saw, then the bordering action is moved in the same document transaction. The atomic history entries themselves are never rewritten.
merge_named_ranges
Merge named bands into one caller-resolved range. Every old record must exist before anything is changed, so a stale UI cannot partially merge a set that a collaborator has already edited.
move_named_boundary
Move the boundary between two named bands while preserving both labels. As with split, the caller resolves the two sides from its displayed causal order and sends exact ids.
name_range
Names the run of changes from start to end, or opens an unbounded run when end is None. Returns the record id (also the document key). The transaction is left open — the host commits, so the naming lands stamped and attributed like any other edit.
read_named_ranges
Records that do not parse (a corrupted key, a missing label) are skipped rather than guessed at — a band in the wrong place is worse than no band.
split_named_range
Split one named band into two adjacent named bands in the current transaction. The caller supplies both boundary ids because a CRDT history is not inherently linear at concurrent branches; guessing adjacency here would make the operation non-deterministic across peers.