1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//! # MeterStore
//!
//! Hot/cold tiered store for metering time series: PostgreSQL holds the recent
//! interval window, Apache Iceberg holds the history, and a single explicit
//! timestamp — the *tiering watermark* — separates them.
//!
//! MeterStore is the persistence layer of the [mako](https://github.com/hupe1980/mako)
//! platform. It stores the types defined by the [`metering`] crate; it does not
//! redefine them and it does not compute with them.
//!
//! ## What this crate owns
//!
//! Exactly three things beyond storage mechanics:
//!
//! 1. **Correction versioning** — [`version`], implementing MSCONS's rule that
//! versions are only comparable within a (network operator, month) scope.
//! 2. **The transaction-time axis** — `recorded_at`, giving bitemporality
//! alongside `metering`'s valid time (`from`/`to`).
//! 3. **The tiering boundary** — [`watermark`].
//!
//! Everything else — DST calendars, unit conversion, quality semantics,
//! validation, Ersatzwertbildung — belongs to [`metering`]. Duplicating any of
//! it here would create a second implementation to keep correct, and it would
//! drift.
//!
//! [`planner`] re-exports `metering::calendar` for convenience, so callers get
//! DST-correct local days without depending on both crates directly. The
//! implementation is upstream and there is only one of it.
//!
//! ## The five things a caller usually wants
//!
//! - [`MeterStore::sql`] — DataFusion's own `DataFrame` over a table that spans
//! both tiers. [`MeterStore::query`] returns the same rows plus the boundary
//! they were computed against (P1).
//! - [`MeterStore::series`] — one measuring point as a `metering`
//! `MeasurementSeries`, version-resolved and tier-split.
//! - [`MeterStore::as_of`] — the same queries against a pinned Iceberg snapshot
//! and an optional version ceiling, for a settlement rerun.
//! - [`MeterStore::completeness`] — whether a range holds what the DST-aware
//! calendar says it should, because a missing interval is information rather
//! than an empty set.
//! - [`MeterCatalog`] — several tables in one session, when a deployment holds
//! more than one stream and needs a statement that mentions both.
//!
//! ## What is stored
//!
//! All four Sparten. `value` carries the quantity and `unit` its dimension,
//! because water is metered *and billed* in m³ and gas may sit on either side of
//! the Brennwert conversion — a column named for kilowatt-hours would be wrong
//! for half of them. A unit the commodity cannot be expressed in is refused at
//! the write.
//!
//! Any declared resolution, not only the quarter-hour: completeness asks
//! `metering`'s calendar per day, so one-minute data expects 1 440 intervals on
//! an ordinary day and 1 500 on the 25-hour autumn one.
//!
//! ## Status
//!
//! Pre-alpha, and **unpublished on purpose**: the API is still settling, and
//! integrating against a real workload is what settles it. Encoding, tiering,
//! streaming archival, tier-split query
//! execution, reproducible reads, completeness, multi-table sessions and both
//! serving surfaces are implemented, and checked against an independently
//! implemented reference over generated workloads ([`testkit`], §17.3) on real
//! PostgreSQL and a real Iceberg warehouse.
//!
//! The output is checked to be readable **without this crate** — the files
//! opened by a bare Parquet reader, the published resolution SQL verified
//! against them, and a real **DuckDB** container reading both the Parquet and
//! the Iceberg metadata and agreeing. That is the substance of the open-format
//! claim.
//!
//! Compression against PostgreSQL row storage is measured on real
//! infrastructure — ~109×, comfortably past the >10× the design targets.
//!
//! Serving surfaces: a read-only Iceberg REST façade (`catalog-facade`) for
//! SQL-catalog deployments, and Flight SQL (`flight`) for the one thing an
//! external client cannot assemble for itself — the unified hot + cold view.
//!
//! Not yet done: interop against Spark, Trino and PyIceberg, and the
//! query-latency benchmarks, so the p99 targets remain aspirational. Compaction
//! and orphan-file cleanup are blocked on the upstream `iceberg` crate.
//!
//! [`MeterStore::sql`]: crate::session::MeterStore::sql
//! [`MeterStore::query`]: crate::session::MeterStore::query
//! [`MeterStore::series`]: crate::session::MeterStore::series
//! [`MeterStore::as_of`]: crate::session::MeterStore::as_of
//! [`MeterStore::completeness`]: crate::session::MeterStore::completeness
//! [`MeterCatalog`]: crate::session::MeterCatalog
// Doc comments throughout cite `§N` — sections of `CONCEPT.md`, the design
// document that lives in the repository and records *why* each decision was
// made. It is not published with the crate, so on docs.rs those citations read
// as pointers into the source repository rather than as links. Everything a
// caller needs to use the crate is here; the citations exist so a maintainer
// changing a behaviour can find the argument it was based on.
/// Arrow, re-exported from DataFusion.
///
/// Sourced through `datafusion` rather than as a direct dependency so the graph
/// cannot contain two incompatible `arrow` versions — a mismatch would make
/// `RecordBatch` and `TableProvider` types mutually unusable. Every module uses
/// `crate::arrow`, never a direct `arrow::` path.
pub use arrow;
pub use ;
pub use ;
pub use canonical_obis;
pub use ;
pub use ;
pub use ;
pub use PostgresHot;
pub use ;
pub use ;
pub use Settings;
pub use ;
pub use ;
pub use ;
/// Common imports for working with MeterStore.