# Functions

Import these from `@grafloria/engine`.

## Functions

### `coalesce`

Drop every `set` that a later `set` in the same batch overwrites.

A stable filter: elements are removed, never reordered. Exported because it is worth
testing on its own, and because it is the part that is easy to get wrong.

RETURNS THE DROPPED OPS TOO, AND THAT IS NOT A CONVENIENCE — IT IS LOAD-BEARING.

An op that is coalesced away is an op the sender HAS (it is in its log) and the receiver
will NEVER have. Anti-entropy compares frontiers derived from logs, so unless the sender
knows exactly which ops it deliberately withheld, its frontier says "I hold 20 ops" while
the peer holds 1 — a gap indistinguishable from a lost packet, which triggers a full
history REPAIR on the next sync round. And the round after. Forever, because the peer can
never obtain ops that will never be sent.

That is a silent O(history) resend after EVERY DRAG — the most common interaction there
is. See `SyncAdapter.suppressed`.

```ts
function coalesce(ops: readonly Op[]): { kept: Op[]; dropped: Op[] }
```

### `createSyncSession`

Build a Replica and a SyncAdapter, correctly wired to each other.

The wiring is one line and it is easy to forget, and forgetting it produces the exact
failure this codebase is famous for: everything green, every unit test passing, and not
one edit ever reaching the wire — because `onLocalOp` went nowhere.

```ts
function createSyncSession(
  diagram: DiagramModel,
  transport: SyncTransport,
  options: SyncSessionOptions
): SyncAdapter
```

### `deltaFor`

THE CATCH-UP DELTA: which of `ours` does a peer with frontier `remote` not have?

Two tiers, and the tier is chosen PER ACTOR:

FAST  — our digest of that actor's ops at-or-below the peer's `max` matches theirs. Their frontier is honest; send only the tail above `max`. REPAIR— it does not match. There is a hole somewhere below their max and neither of
          us can say where. Send everything we have from that actor and let their log
          de-duplicate. Over-sending is free. Under-sending loses the document.

Returns ops in TOTAL ORDER — so a receiver that applies them in array order applies an
`add` before the `set`s that depend on it, and the causal buffer has nothing to do.

```ts
function deltaFor(
  ours: readonly Op[],
  remote: VersionVectorJSON
): { ops: Op[]; repairedActors: ActorId[] }
```

### `isDocumentMessage`

True for the ONE message kind that is allowed to touch the durable log.

```ts
function isDocumentMessage(msg: SyncMessage): msg is OpsMessage
```

### `mulberry32`

Deterministic PRNG (mulberry32). A fuzz you cannot replay is an anecdote.

```ts
function mulberry32(seed: number): () => number
```
