Skip to content

Commit dce658e

Browse files
authored
Merge pull request #31 from IntentFile/docs/rollup-child-update
docs: a roll-up recomputes on the child's update too
2 parents c063066 + 2ea201a commit dce658e

1 file changed

Lines changed: 3 additions & 1 deletion

File tree

docs/spec/glue.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,10 +438,12 @@ rollups:
438438
status: Status, statusWhenFull: 7, statusWhenPartial: 6 }
439439
```
440440

441-
A count roll-up keeps a counter on a parent current on the child's create / delete. With `op: sum` the roll-up keeps `field` equal to the sum of the children's `of` field, can maintain a `balance` (= `capacity - sum`), and can flip a `status` relation to `statusWhenFull` / `statusWhenPartial`. Sum roll-ups **compose transitively** across a multi-level composition (a leaf edit updates the mid total, then the top total); recomputation stops when values stop changing.
441+
A count roll-up keeps a counter on a parent current as its children change. With `op: sum` the roll-up keeps `field` equal to the sum of the children's `of` field, can maintain a `balance` (= `capacity - sum`), and can flip a `status` relation to `statusWhenFull` / `statusWhenPartial`. Sum roll-ups **compose transitively** across a multi-level composition (a leaf edit updates the mid total, then the top total); recomputation stops when values stop changing.
442442

443443
Roll-ups are recompute-on-event (self-healing), so they are **eventually consistent, not transactionally exact** under heavy concurrency.
444444

445+
Every roll-up recomputes on the child's **create, update and delete**, whatever its `op` reduces the children to - the event set belongs to the construct, not to the aggregation. The update pass is what a plain counter needs most: a child changes parents by an ordinary edit of its own parent relation, so an edit that re-parents a child recomputes the parent it moved *to*. The parent it moved *away from* is not named by that event; a generator that publishes a distinct event for a moved key should recompute it too, and otherwise it converges the next time one of its own children changes.
446+
445447
The parent may be owned by **another model**. When the roll-up's `via` relation is a cross-model reference, the child stays local - it owns the event that drives the recompute - while the parent's coordinates come from the owner's model, so a time-tracking model can maintain an `actualHours` total on a project the projects model owns. The referenced model must be declared in `uses`, and the parent field is validated against the owner's model at generation time; an unresolvable roll-up is reported rather than dropped silently. The `capacity` / `balance` / `status` variants stay local-only, since they read the parent's own limit and status values.
446448

447449
## aggregates — keyed cross-entity totals

0 commit comments

Comments
 (0)