Streamhouse · STH-07
Serving layer — OLAP on the streamhouse
From your world. Athena/Redshift serving marts: a dashboard reads a small pre-aggregated table, not the raw fact
Serve a sub-second dashboard off the streaming revenue mart
You run the serving layer on a streamhouse. Upstream, streams feed a Paimon primary-key fact
fct_orders (keyed by order_id, merge-engine=partial-update). Its merged state is one row per
order with the final revenue. A revenue dashboard must answer in about a second. It filters to one
company.
Your job: load the merged state into DuckDB once. Build a small pre-aggregated serving rollup. Answer the dashboard query from the rollup (pruned by company), not from the raw fact.
What you implement (solution.py)
def load_serving(con, rows): ... # build fct_orders + the mart_daily rollup in `con`
def dashboard_query(con, company): ... # top days by revenue for one company, from mart_daily
def olap_scan(con, company): ... # same aggregate computed directly from the raw merged rows
conis an in-memory DuckDB connection (the serving engine).rowsis the merged mart state. It is a list of dicts with keysorder_id(int),company(str),order_day(strYYYY-MM-DD),revenue(int, minor units). The upstream Paimon merge has already deduplicated these rows to the latest value perorder_id. You do not re-merge.
load_serving(con, rows)
- Load
rowsinto a DuckDB table namedfct_orders(columns above). - Build a small rollup table named
mart_daily=SELECT company, order_day, SUM(revenue) AS revenue FROM fct_orders GROUP BY company, order_day. The dashboard reads this table.
dashboard_query(con, company)
Return a list of (order_day, revenue) tuples for company. Order them by revenue DESC, then
order_day ASC. The query MUST read from mart_daily and apply the company predicate (so the
plan prunes). It must not scan fct_orders.
olap_scan(con, company)
Compute the same result directly from the raw merged rows (fct_orders). The tests use it as
the OLAP-vs-rollup reconciliation. Return the same shape as dashboard_query.
Constraints
revenueisSUM(revenue), in minor units (integer).- Do not iterate a changelog and do not re-deduplicate. The input is already merged.
mart_dailymust be strictly smaller thanfct_ordersfor realistic input (pre-aggregation).
How the tests grade you (G1–G6)
- The dashboard result reconciles with an independent DuckDB oracle over the same merged rows
(G6). It equals
olap_scanfor every company. EXPLAIN dashboard_queryreferencesmart_dailyand neverfct_orders(pruning / plan).- Wall-clock time is only a generous guardrail. The tests do a warm-up. Then the median of several runs must beat a comfortable budget (this is robust on a loaded machine).
- The tests cross-check the upstream merged state against a batch "latest per key" rebuild (the streaming-vs-batch invariant).
Starter code
"""STH-07 / 01-serving-mart — starter. See README.md.
Build the serving rollup and answer the dashboard from it (not from the raw
fact). Replace the NotImplementedError bodies.
"""
def load_serving(con, rows):
# TODO: load `rows` into a DuckDB table `fct_orders` (order_id, company,
# order_day, revenue), then build a small pre-aggregated rollup table
# `mart_daily` = SUM(revenue) GROUP BY company, order_day.
raise NotImplementedError
def dashboard_query(con, company):
# TODO: return [(order_day, revenue), ...] for `company`, ordered by revenue
# DESC then order_day ASC, reading from `mart_daily` (NOT fct_orders).
raise NotImplementedError
def olap_scan(con, company):
# TODO: the same aggregate computed directly from the raw `fct_orders`.
raise NotImplementedError
Hints
Hint 1
Serving reads the MERGED state, not the changelog. The test hands you the merged rows (latest per order_id). Load them into DuckDB once, then build a SMALL pre-aggregated rollup table `mart_daily` = SUM(revenue) GROUP BY company, order_day.
Hint 2
The dashboard query must read `mart_daily` (not the raw `fct_orders`) and apply the company predicate so a columnar engine prunes it. Return rows ordered by revenue DESC. The EXPLAIN of your dashboard query must mention `mart_daily` and must NOT scan `fct_orders`.
Hint 3
SUM(revenue) — not COUNT(*), not AVG. Keep the company filter in the dashboard query. The OLAP recompute (`olap_scan`) reads the raw merged rows directly and must agree with the rollup-backed dashboard (G6 oracle).
uv run de start STH-07/01-serving-mart
# edit workspace/STH-07/01-serving-mart/
uv run de test