Tamale.Transport (tamale v0.1.0)

Copy Markdown

Anchor transport along the op log — the whole of rebase.

transport(anchor, space) = fold(anchor, log[anchor.at_version..head])

The result is three-valued, matching the three shapes a morphism between two space versions can take — plus a first-class fourth for partial survival, which only Anchor.Metric can produce:

  • {:ok, anchor'} — well-defined
  • {:clip, covered, lost} — part of the support survived (Metric only): covered are the surviving image anchors, lost the old-coordinate sub-intervals with no image. How much loss is tolerable is the channel's call, so the kernel surfaces it verbatim.
  • {:ambiguous, candidates} — one-to-many; a policy choice is required. Not produced by the kernel's own conventions (they are deliberately deterministic); reserved so policy layers share the result type.
  • {:undefined, reason} — the referent is gone

Ordinal semantics

  • refs are conjunctive: Delete of any ref is terminal
  • Split continues identity on the first child (kernel convention)
  • Merge remaps refs onto into
  • adjacent? is judged on the head state after the fold. ids are never reused and deletes are irreversible, so only the net effect can matter — a mid-log break that is restored by head leaves no residue.
  • an adjacent? anchor names the boundary between its refs: a Merge that collapses them removes the boundary, and the anchor dies with {:undefined, :boundary_merged}. Plain conjunctive refs instead deduplicate onto into and survive — judging whether the edit still means something is Tamale.Patch.resolve/2's job, not transport's
  • refs that are not live at head — or that were not yet live at at_version (the Insert, or the Split, that created them shows up in the folded log) — indicate a Caller bug at mount time and are reported as {:error, {:unknown_ref, id}}, not silently kept

Metric semantics

Metric anchors travel by warp, not by identity. The kernel holds no element spans and no tempo map, so the Caller supplies a warp_provider(coord, log_entry) -> {:ok, Warp.t()} | {:error, term()} — and transport folds the per-entry warps into one (Warp.compose/2, oldest first), then maps the anchor interval through it (Warp.map_interval/3). A provider {:error, reason} aborts the fold and surfaces as this transport's own {:error, reason} — a surfaced failure, never a crash. Interval mapping outcomes:

  • full coverage → {:ok, anchor'} (including being stretched over an insertion)
  • partial coverage → {:clip, [%Anchor.Metric{}], lost}
  • no coverage → {:undefined, :outside_warp}

The folded warp is available on its own — fold_warp/4, called with the same arguments — for transforming the payload alongside its anchor (Tamale.ChannelAdapter.warp_payload/2).

Relative semantics

A Relative anchor is its host ref: transported with Ordinal rules, offsets untouched (a host stretch does not rescale "0–50 ms after the start"). Offsets are cast to rational coordinates at entry — floats are {:error, {:invalid_coordinate, value}}. The absolute interval is derived at use time from the host's current span — see Tamale.Anchor.project/3. Offsets may be negative and may overhang the host; there is no within-host invariant.

Summary

Types

Supplies the warp for one log entry in one coordinate system.

Functions

Folds the per-entry warps the provider supplies for log[from_version..head] into one, oldest first (Warp.compose/2, starting from Warp.identity/0). This is exactly the fold transport/3 performs internally — call it with the same arguments to obtain the warp that carries a payload alongside its Tamale.Anchor.Metric (Tamale.ChannelAdapter.warp_payload/2), for both the {:ok, anchor'} and the {:clip, covered, lost} outcomes.

Transports a Tamale.Anchor.Metric along the log, folding the warps the provider supplies for each entry (coord is passed through so one provider can serve several coordinate systems).

Types

result()

@type result() ::
  {:ok, Tamale.Anchor.t()}
  | {:clip, [Tamale.Anchor.Metric.t()], [Tamale.Warp.interval()]}
  | {:ambiguous, [Tamale.Anchor.t()]}
  | {:undefined, term()}

warp_provider()

@type warp_provider() :: (term(), Tamale.Space.entry() ->
                      {:ok, Tamale.Warp.t()} | {:error, term()})

Supplies the warp for one log entry in one coordinate system.

May return {:error, reason} when a warp cannot be constructed for the entry — the fold aborts and the error surfaces as the transport result.

Functions

fold_warp(coord, space, from_version, warp_provider)

@spec fold_warp(term(), Tamale.Space.t(), Tamale.version(), warp_provider()) ::
  {:ok, Tamale.Warp.t()} | {:error, term()}

Folds the per-entry warps the provider supplies for log[from_version..head] into one, oldest first (Warp.compose/2, starting from Warp.identity/0). This is exactly the fold transport/3 performs internally — call it with the same arguments to obtain the warp that carries a payload alongside its Tamale.Anchor.Metric (Tamale.ChannelAdapter.warp_payload/2), for both the {:ok, anchor'} and the {:clip, covered, lost} outcomes.

from_version errors are explicit, as in Space.log_from/2: {:error, {:future_version, v}} and {:error, :log_truncated}.

transport(anchor, space)

@spec transport(Tamale.Anchor.t(), Tamale.Space.t()) :: result() | {:error, term()}

transport(anchor, space, warp_provider)

@spec transport(Tamale.Anchor.Metric.t(), Tamale.Space.t(), warp_provider()) ::
  result() | {:error, term()}

Transports a Tamale.Anchor.Metric along the log, folding the warps the provider supplies for each entry (coord is passed through so one provider can serve several coordinate systems).

The interval endpoints are cast to rational coordinates up front: floats are {:error, {:invalid_coordinate, value}}, and from > to is {:error, :invalid_interval}.