Story: Generalize as-of and as-of-bucket queries across repositories
Table of Contents
This page documents a story in Product backlog — inbox, carried unfinished from Sprint 24 at close. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
Goal
Two distinct, general-purpose query shapes were built bespoke for
market_observations_repository (curve-snapshot-builder-viewer
task) and should be recognised and generalised as reusable patterns
rather than staying one-off:
- As-of: for a set of independently-updating rows sharing a key
family (e.g. one row per
point_idwithin aseries_id), return the latest row per key at or before a given time —SELECT DISTINCT ON (key) ... WHERE ... <as_of ORDER BY key, time DESC=. Needs a supporting index ordered key-first, not time-first. - As-of buckets: N as-of snapshots at regular time intervals
ending at a given boundary, computed as one SQL statement
(
generate_series()for the boundaries, aLATERALsubquery doing the per-bucket as-of reduction), not N round trips of the as-of query.
Distinct from the bitemporal "as-of" already documented in Time
and Timestamps / temporal_composite_entity_versioning
(valid_from < t < valid_to= — correction history for one entity
instance). This pattern is about multiple independently-ticking
rows sharing a key family, reconstructing a snapshot across a set.
compute_telemetry_repository::latest_node_samples() already used
the identical shape for per-host latest telemetry before this story
existed — the shape recurs, but nobody has named or captured it as
reusable until now.
Status
| Field | Value |
|---|---|
| State | BACKLOG |
| Carried from | Sprint 24 (unfinished at close) |
| Now | Not yet started. |
| Waiting on | Nothing. |
| Next | Decide shared-helper vs. documented-reference-implementation approach first. |
| Last touched | 2026-07-21 |
Acceptance
- The as-of and as-of-bucket query shapes are documented as reusable patterns (reference implementation: market_observations_repository::read_as_of()/read_as_of_buckets()).
- Either a shared ores.database helper exists generating the parameterised SQL for both shapes, or a documented decision exists to defer the helper until a second concrete caller needs it, keeping the reference implementation as the copy-from source in the meantime.
- The "buckets are one DB query, not a C++ loop over N as-of calls" principle is captured as a hard rule somewhere discoverable (a knowledge doc or repository-layer convention doc), not left to be rediscovered per repository.
Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
Decisions
Out of scope
- Building the shared helper immediately if only one real caller exists — avoid premature abstraction from a single caller (see Acceptance).
References
projects/ores.marketdata/core/src/repository/market_observations_repository.cpp—read_as_of()=/=read_as_of_buckets(), the reference implementation this story is distilled from.projects/ores.marketdata/modeling/ores.marketdata.market_observation.org— theobservations_series_point_datetime_idxindex entry.projects/ores.compute/core/src/repository/compute_telemetry_repository.cpp—latest_node_samples(), an earlier, independent instance of the same shape.
See also
- Curve snapshot builder/viewer — the task this was raised from.
- Time and Timestamps — the bitemporal (transaction-time) "as-of", a different but related concept.