Task: Tick the window
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 change recorded in the coalescer reaches a stream without anyone calling the pump.
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 change recorded between ticks reaches an open stream on the next tick.[X]A stopped ticker publishes nothing further.[X]The ticker does not hold the thread between ticks.
4. Plan
One coroutine loop, one timer, re-armed per tick. A quiet system pays a timer per interval and no thread, which is the same argument the keep-alive makes: the stream is idle by design and idle must be free.
The loop checks the stop flag after every wait, so a drain ends on the tick in progress rather than in the middle of publishing a window.
5. Measurements
| What | Value | Command | Commit |
|---|---|---|---|
| Ticker cases | 3 cases, 7 assertions, all passing | ./ores.http.core.tests "[change_ticker]" |
this branch |
Whole ores.http.core suite |
36 cases, 157 assertions, all passing | ./ores.http.core.tests |
this branch |
6. Notes
- The stopped case restarts the io_context and records a change afterwards, because a ticker that merely stopped re-arming would pass a weaker case: this one proves it writes nothing at all.
- The ticker is not wired into the server yet. It belongs beside the feed that records the events, because a ticker over an empty coalescer is an interval that does nothing and a reader would have to hunt for the missing half.
7. Result
The window closes itself. Combined with the coalescer and the pump, the path from a recorded change to a client needs no caller: record, tick, drain, format, fan out.