Story: Let the blotter read a page, not the book

Table of Contents

This page documents a story in Sprint 29. It captures the goal, current status, acceptance criteria, and the tasks that compose it.

1. Goal

A desk opens the blotter and has its rows in well under a second, at any size the tenant has written, and its rail states how many rows sit at each node without reading the book to find out.

The screen asks two questions, and they are different questions: give me one page of rows, and give me a count at each node. Both have their operation on main, and both still read the union view, so a page pays for each row's laterals and sorts the book to take the first hundred rows. That is what the tasks below take away.

2. Status

Field Value
State DONE
Parent sprint Sprint 29
Now Nothing.
Waiting on Nothing.
Next Nothing.
  • The contract comes first, the store behind it. Two new operations carry the screen: one page of rows, keyed by the sort key and the row id, and one rail of counts. They are implemented over the summary view first, so the screen's answers are correct and measurable at the size we have, and the store behind them changes when the model does. Deciding the contract before the store keeps the store replaceable.
  • The rail is counted by the store. A count at each node is one grouped read; the client never counts rows it retrieved to draw a page.
  • A package is a trade, so there is no projection. Trade Structures and Deal Composition states that a structure is one deal whose legs are themselves trades, and that this tree's CompositeTrade is the structure. The blotter row is therefore a trade, with its own booking and state, and the union it was computed from is the defect. The projection table, its rebuild and its alarm are closed: see The blotter lists trades.
  • Search is left as the summary states it today: the identifiers and the references, concatenated into one column. A trigram index waits until a search is measured to need one.
  • Flat mode is a filter on the same rows, not a second model: the composite carries its legs and the top list filters them out.
  • The order is an index. A page is ordered by a column of a table, compared in the column's own type, so a keyset page is a scan from the key and not a sort of the book.
  • The refactor runs before the screen is measured again. Four tasks make a package a trade, and one makes the order indexable. The plan is The blotter lists trades.
  • History: the blotter reads the current state only, as the summary view already states. As-of would make the projection bitemporal; nothing asks for it.

3. Tasks

Task State Start End Description
Answer the rail from one grouped read DONE   2026-11-03 The rail's figures are counted from every row in the book. Give the store one read that answers the counts at each node of every rail, and the service one operation that returns them.
Page the blotter by keyset DONE   2026-11-03 An offset page re-walks what it skips, so the hundredth page costs more than the first. Page by the sort key and the row id, so every page costs what the first costs.
Hold the blotter row as a projection ABANDONED   2026-11-02 The summary view joins four correlated subqueries per row, so neither a page nor a count can be read without them. Project one row per blotter row, write it where the facts are written, and rebuild it from the facts in a test. Closed: a package is a trade, so there is no projection to hold.

4. Out of scope

  • Any change to the BFF. It is being replaced by ores.http, and a read model written around it would be thrown away.
  • The screen's layout and interaction, except where the read model forces a change (paging, the rail's source).
  • The other screens that read the summary view; they are separate stories unless they share the read model.

Emacs 29.3 (Org mode 9.6.15)