Task: Coalesce a burst into one frame

Table of Contents

This page documents a task in the Stream the changes as they happen story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

A burst of changes reaches a client as one frame per entity, not one per row.

2. Status

Field Value
State DONE
Parent story Stream the changes as they happen
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-31

3. Acceptance

  • [X] A burst of changes in one window becomes one frame per entity.
  • [X] Two entities in one window become two frames.
  • [X] A change is never attributed to another tenant or party.
  • [X] A second window emits only what changed in it.

4. Plan

A dirty set keyed by tenant, party and entity, and a drain that swaps the map and turns each entry into a frame. The key carries the tenant and party because a frame is addressed at one party's data: folding two parties into one frame would tell a client to redraw rows it may not read.

The identifiers are a set, so a row written twice in one window is one dirty identifier, and a drained window is empty until something changes again.

5. Measurements

What Value Command Commit
Coalescer cases 6 cases, 25 assertions, all passing ./ores.http.core.tests "[change_coalescer]" this branch
Whole ores.http.core suite 28 cases, 138 assertions, all passing ./ores.http.core.tests this branch

6. Notes

  • The burst case records 1000 rows and asserts one frame with 1000 ordered identifiers, which is the exit criterion of increment B3 stated as a case.
  • A change with no entity or no identifier is dropped: it names nothing a client could redraw, and queueing it would make the frame lie about what changed.
  • Nothing calls record yet. The feed that subscribes to the change events is the next task, and the tick that drains this belongs beside it.

7. Result

The coalescer turns a burst into frames a screen can use: one per entity per window, addressed at one party, ordered, deduplicated, and empty once drained.

Emacs 29.3 (Org mode 9.6.15)