export

suspend fun export(span: SpanRecord): ExportResult

Export one span: insert it into the CRDT and durably flush to store.

If a WarpCausalClock was supplied, an unstamped span is auto-stamped with causal context before insert (#846) — an explicit SpanRecord.causalStamp always wins.

Crash-window invariant (#1053)

The clock is persisted before the span's durable write, establishing the invariant the durable clock seq is always ≥ every durable span's dot. A crash in the two-write window can then only lose the span (retried on the next export) — it can never strand a persisted span at a dot the recovered clock would re-mint. Persisting the span first (the reverse order) leaves that hole: span at seq=N durable, clock still <N, and the next WarpCausalClock.tick on restart re-mints N, violating the clock's uniqueness guarantee.

The invariant holds unconditionally, including under concurrent export() on a multi-threaded dispatcher: the clock persist and the span write are serialized as one ordered unit by an internal coroutine Mutex, so the last durable clock write always reflects a seq ≥ every durable span's dot rather than being clobbered by an older concurrent snapshot. The span snapshot is re-encoded inside that section, so a concurrent add is never dropped by a stale snapshot either.

If either durable write fails, a freshly-minted stamp is rolled back out of the in-memory set so a retrying caller re-adds exactly one copy rather than accumulating a second stamped copy of the same span. The minted dot's seq is left spent — a harmless gap, since the durable clock already covers it.

Returns ExportResult.Success after the durable write. Returns ExportResult.Failure only if the store itself throws; the CRDT mutation is never committed without a successful store write.

When the buffer is full, the eviction policy fires first, logging the dropped span, then the new span is inserted.