Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions analytics/models/read_models/activity_location_sample.sql
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,21 @@ WITH activity_members AS (

location_versions AS (
SELECT *
FROM {{ source('postgres_fitness', 'metric_stream_freshness') }}
FROM {{ source('ingest', 'metric_stream_freshness') }}
WHERE channel = 'location'
AND (point IS NOT NULL OR _peerdb_is_deleted = 1)
AND (point IS NOT NULL OR is_deleted = 1)
),

location_rows AS (
SELECT
id,
argMax(activity_id, _peerdb_version) AS member_activity_id,
argMax(user_id, _peerdb_version) AS user_id,
argMax(recorded_at, _peerdb_version) AS recorded_at,
argMax(provider_id, _peerdb_version) AS provider_id,
argMax(point, _peerdb_version) AS point,
argMax(_peerdb_synced_at, _peerdb_version) AS _peerdb_synced_at,
argMax(_peerdb_is_deleted, _peerdb_version) AS is_deleted
argMax(activity_id, version) AS member_activity_id,
argMax(user_id, version) AS user_id,
argMax(recorded_at, version) AS recorded_at,
argMax(provider_id, version) AS provider_id,
argMax(point, version) AS point,
argMax(ingested_at, version) AS ingested_at,
argMax(is_deleted, version) AS is_deleted
FROM location_versions
GROUP BY id
),
Expand Down Expand Up @@ -96,7 +96,7 @@ SELECT
)) AS lng,
toUInt64(toUnixTimestamp64Nano(now64(9))) AS refresh_version,
location_rows.is_deleted AS is_deleted,
greatest(location_rows._peerdb_synced_at, activity_members.source_synced_at) AS source_refreshed_at,
greatest(location_rows.ingested_at, activity_members.source_synced_at) AS source_refreshed_at,
source_refreshed_at AS refreshed_at
FROM location_points AS location_rows
INNER JOIN activity_members
Expand Down
8 changes: 4 additions & 4 deletions analytics/models/read_models/provider_stats.sql
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ WITH current_providers AS (
SELECT DISTINCT
user_id,
provider_id
FROM {{ source('postgres_fitness', 'metric_stream') }} FINAL
WHERE _peerdb_is_deleted = 0
FROM {{ source('ingest', 'metric_stream') }} FINAL
WHERE is_deleted = 0

UNION DISTINCT

Expand Down Expand Up @@ -175,8 +175,8 @@ metric_stream_counts AS (
user_id,
provider_id,
count() AS count
FROM {{ source('postgres_fitness', 'metric_stream') }} FINAL
WHERE _peerdb_is_deleted = 0
FROM {{ source('ingest', 'metric_stream') }} FINAL
WHERE is_deleted = 0
GROUP BY user_id, provider_id
),

Expand Down
23 changes: 9 additions & 14 deletions analytics/models/read_models/read_model_microbatch.sql.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,20 +259,15 @@ describe("production analytics read-model build", () => {

expect(sourcesYaml).toContain("name: metric_stream_freshness");
expect(sourcesYaml).toContain("identifier: metric_stream");
expect(sourcesYaml).toContain("event_time: _peerdb_synced_at");
expect(sensorScalarSampleSql).toContain("event_time='_peerdb_synced_at'");
expect(sensorScalarSampleSql).toContain(
"source('postgres_fitness', 'metric_stream_freshness')",
);
expect(sourcesYaml).toContain("name: ingest");
expect(sourcesYaml).toContain("event_time: ingested_at");
expect(sensorScalarSampleSql).toContain("event_time='ingested_at'");
expect(sensorScalarSampleSql).toContain("source('ingest', 'metric_stream_freshness')");
expect(dedupedSensorSql).toContain("event_time='refreshed_at'");
expect(dedupedSensorSql).toContain("max(samples._peerdb_synced_at) AS source_refreshed_at");
expect(dedupedSensorSql).toContain("source_refreshed_at AS refreshed_at");
expect(activityLocationSampleSql).toContain(
"source('postgres_fitness', 'metric_stream_freshness')",
);
expect(activityLocationSampleSql).not.toContain(
"source('postgres_fitness', 'metric_stream')",
);
expect(activityLocationSampleSql).toContain("source('ingest', 'metric_stream_freshness')");
expect(activityLocationSampleSql).not.toContain("source('postgres_fitness', 'metric_stream')");
});

it("materializes activity location membership as a microbatch intermediary", () => {
Expand All @@ -282,11 +277,11 @@ describe("production analytics read-model build", () => {
expect(sql).toContain("incremental_strategy='microbatch'");
expect(sql).toContain("event_time='refreshed_at'");
expect(sql).toContain("lookback=3");
expect(sql).toContain("source('postgres_fitness', 'metric_stream_freshness')");
expect(sql).toContain("source('ingest', 'metric_stream_freshness')");
expect(sql).toContain("ref('deduped_activity_members')");
expect(sql).not.toContain("source('analytics', 'v_activity_members')");
expect(sql).toContain("channel = 'location'");
expect(sql).toContain("argMax(point, _peerdb_version) AS point");
expect(sql).toContain("argMax(point, version) AS point");
expect(sql).toContain("toString(point) AS point_text");
expect(sql).toContain("startsWith(location_rows.point_text, '{')");
expect(sql).toContain("JSONExtract(location_rows.point_text, 'coordinates', 'Array(Float64)')[2]");
Expand Down Expand Up @@ -319,7 +314,7 @@ describe("production analytics read-model build", () => {
);
expect(activitySensorSampleSql).toContain("source_refreshed_at AS refreshed_at");
expect(activityLocationSampleSql).toContain(
"greatest(location_rows._peerdb_synced_at, activity_members.source_synced_at) AS source_refreshed_at",
"greatest(location_rows.ingested_at, activity_members.source_synced_at) AS source_refreshed_at",
);
expect(activityLocationSampleSql).toContain("source_refreshed_at AS refreshed_at");
expect(activityLocationSampleSql).not.toContain("now64(9) AS refreshed_at");
Expand Down
17 changes: 10 additions & 7 deletions analytics/models/sources.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ sources:
tables:
- name: v_activity
- name: v_activity_members
- name: ingest
schema: ingest
tables:
- name: metric_stream
config:
event_time: recorded_at
- name: metric_stream_freshness
identifier: metric_stream
config:
event_time: ingested_at
- name: postgres_fitness
schema: postgres_fitness
tables:
Expand All @@ -17,13 +27,6 @@ sources:
- name: journal_entry
- name: lab_panel
- name: lab_result
- name: metric_stream
config:
event_time: recorded_at
- name: metric_stream_freshness
identifier: metric_stream
config:
event_time: _peerdb_synced_at
- name: provider
- name: provider_priority
- name: sensor_device_priority
Expand Down
30 changes: 15 additions & 15 deletions analytics/models/staging/sensor_scalar_sample.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
materialized='incremental',
incremental_strategy='microbatch',
unique_key='id',
event_time='_peerdb_synced_at',
event_time='ingested_at',
begin='2026-01-01',
batch_size='day',
lookback=3,
Expand All @@ -17,8 +17,8 @@

WITH metric_stream_versions AS (
SELECT *
FROM {{ source('postgres_fitness', 'metric_stream_freshness') }}
WHERE (scalar IS NOT null OR _peerdb_is_deleted = 1)
FROM {{ source('ingest', 'metric_stream_freshness') }}
WHERE (scalar IS NOT null OR is_deleted = 1)
AND channel IN (
'heart_rate',
'power',
Expand All @@ -41,15 +41,15 @@ WITH metric_stream_versions AS (
metric_stream_rows AS (
SELECT
id,
argMax(user_id, _peerdb_version) AS user_id,
argMax(recorded_at, _peerdb_version) AS recorded_at,
argMax(channel, _peerdb_version) AS channel,
argMax(provider_id, _peerdb_version) AS provider_id,
argMax(device_id, _peerdb_version) AS device_id,
coalesce(argMax(scalar, _peerdb_version), 0) AS scalar,
argMax(_peerdb_synced_at, _peerdb_version) AS _peerdb_synced_at,
argMax(_peerdb_is_deleted, _peerdb_version) AS _peerdb_is_deleted,
max(_peerdb_version) AS source_peerdb_version
argMax(user_id, version) AS user_id,
argMax(recorded_at, version) AS recorded_at,
argMax(channel, version) AS channel,
argMax(provider_id, version) AS provider_id,
argMax(device_id, version) AS device_id,
coalesce(argMax(scalar, version), 0) AS scalar,
argMax(ingested_at, version) AS ingested_at,
argMax(is_deleted, version) AS is_deleted,
max(version) AS source_version
FROM metric_stream_versions
GROUP BY id
),
Expand Down Expand Up @@ -113,9 +113,9 @@ SELECT
active_sensor_provider_priority.priority,
1000
) AS provider_priority,
metric_stream_rows._peerdb_synced_at AS _peerdb_synced_at,
metric_stream_rows._peerdb_is_deleted AS _peerdb_is_deleted,
metric_stream_rows.source_peerdb_version AS _peerdb_version
metric_stream_rows.ingested_at AS _peerdb_synced_at,
metric_stream_rows.is_deleted AS _peerdb_is_deleted,
metric_stream_rows.source_version AS _peerdb_version
FROM metric_stream_rows
LEFT JOIN active_sensor_provider_priority
ON active_sensor_provider_priority.provider_id = metric_stream_rows.provider_id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const reader: MetricStreamClickHouseReader = {

async function seed(rows: SeedRow[]): Promise<void> {
await client.insert?.({
table: "postgres_fitness.metric_stream",
table: "ingest.metric_stream",
format: "JSONEachRow",
values: rows.map((row) => ({
id: row.id,
Expand All @@ -51,7 +51,7 @@ describe("HeartRateRepository (integration)", () => {
await client.command({ query: statement });
}
await client.command({
query: "DELETE FROM postgres_fitness.metric_stream WHERE user_id = {userId:UUID}",
query: "DELETE FROM ingest.metric_stream WHERE user_id = {userId:UUID}",
query_params: { userId: testUserId },
});

Expand Down Expand Up @@ -147,7 +147,7 @@ describe("HeartRateRepository (integration)", () => {

afterAll(async () => {
await client.command({
query: "DELETE FROM postgres_fitness.metric_stream WHERE user_id = {userId:UUID}",
query: "DELETE FROM ingest.metric_stream WHERE user_id = {userId:UUID}",
query_params: { userId: testUserId },
});
await client.close?.();
Expand Down
4 changes: 2 additions & 2 deletions packages/server/src/repositories/heart-rate-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ export class HeartRateRepository {
provider_id,
toStartOfMinute(toDateTime(recorded_at)) AS minute_bucket,
scalar
FROM postgres_fitness.metric_stream FINAL
FROM ingest.metric_stream FINAL
WHERE user_id = {userId:String}
AND channel = 'heart_rate'
AND _peerdb_is_deleted = 0
AND is_deleted = 0
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
AND scalar > 0
-- Range over the raw recorded_at so the ORDER BY key can prune,
-- instead of wrapping it in toDate(). Bounds are the user's local
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const clickHouse: BodyClickHouseStore = {

async function seed(rows: SeedRow[]): Promise<void> {
await client.insert?.({
table: "postgres_fitness.metric_stream",
table: "ingest.metric_stream",
format: "JSONEachRow",
values: rows.map((row) => ({
id: row.id,
Expand Down Expand Up @@ -72,7 +72,7 @@ describe("ProviderDetailRepository metric stream (integration)", () => {
await client.command({ query: statement });
}
await client.command({
query: "DELETE FROM postgres_fitness.metric_stream WHERE user_id = {userId:UUID}",
query: "DELETE FROM ingest.metric_stream WHERE user_id = {userId:UUID}",
query_params: { userId: testUserId },
});
await seed([
Expand Down Expand Up @@ -137,7 +137,7 @@ describe("ProviderDetailRepository metric stream (integration)", () => {

afterAll(async () => {
await client.command({
query: "DELETE FROM postgres_fitness.metric_stream WHERE user_id = {userId:UUID}",
query: "DELETE FROM ingest.metric_stream WHERE user_id = {userId:UUID}",
query_params: { userId: testUserId },
});
await client.close?.();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe("tableInfo", () => {
["bodyMeasurements", "analytics.v_body_measurement", "recorded_at", "id"],
["foodEntries", "fitness.food_entry", "date", "id"],
["healthEvents", "fitness.health_event", "start_date", "id"],
["metricStream", "postgres_fitness.metric_stream", "recorded_at", "id"],
["metricStream", "ingest.metric_stream", "recorded_at", "id"],
["nutritionDaily", "fitness.v_nutrition_daily", "date", "date"],
["labPanels", "fitness.lab_panel", "recorded_at", "id"],
["labResults", "fitness.lab_result", "recorded_at", "id"],
Expand Down Expand Up @@ -226,8 +226,8 @@ describe("ProviderDetailRepository", () => {

expect(query).toHaveBeenCalledTimes(1);
// Reads the deduped Redpanda-fed mirror, not Postgres.
expect(query.mock.calls[0]?.[1]).toContain("postgres_fitness.metric_stream FINAL");
expect(query.mock.calls[0]?.[1]).toContain("_peerdb_is_deleted = 0");
expect(query.mock.calls[0]?.[1]).toContain("ingest.metric_stream FINAL");
expect(query.mock.calls[0]?.[1]).toContain("is_deleted = 0");
// recorded_at is rendered in UTC so the literal 'Z' suffix is accurate.
expect(query.mock.calls[0]?.[1]).toContain("'%Y-%m-%dT%H:%i:%S.%fZ', 'UTC'");
expect(query.mock.calls[0]?.[2]).toStrictEqual({
Expand Down Expand Up @@ -480,7 +480,7 @@ describe("ProviderDetailRepository", () => {
idColumn: "id",
});
expect(tableInfo("metricStream")).toStrictEqual({
table: "postgres_fitness.metric_stream",
table: "ingest.metric_stream",
orderColumn: "recorded_at",
idColumn: "id",
});
Expand Down
10 changes: 5 additions & 5 deletions packages/server/src/repositories/provider-detail-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function tableInfo(dataType: DataType): {
return { table: "fitness.health_event", orderColumn: "start_date", idColumn: "id" };
case "metricStream":
return {
table: "postgres_fitness.metric_stream",
table: "ingest.metric_stream",
orderColumn: "recorded_at",
idColumn: "id",
};
Expand Down Expand Up @@ -231,7 +231,7 @@ export class ProviderDetailRepository {
readonly #userId: string;
// ClickHouse query runner. Serves the read-models that have moved off
// Postgres: body measurements (analytics.v_body_measurement) and the
// Redpanda-fed metric stream (postgres_fitness.metric_stream).
// Redpanda-fed metric stream (ingest.metric_stream).
readonly #clickHouse: BodyClickHouseStore | undefined;

constructor(
Expand Down Expand Up @@ -335,7 +335,7 @@ export class ProviderDetailRepository {
/**
* Raw metric-stream rows for a provider, read from the Redpanda-fed ClickHouse
* mirror (Postgres `fitness.metric_stream` is retired). Version-deduplicated
* (`FINAL` + `_peerdb_is_deleted = 0`); recorded_at formatted to ISO-8601 Z.
* (`FINAL` + `is_deleted = 0`); recorded_at formatted to ISO-8601 Z.
*/
async #queryMetricStreamRecords(
providerId: string,
Expand Down Expand Up @@ -363,10 +363,10 @@ export class ProviderDetailRepository {
channel,
activity_id,
scalar
FROM postgres_fitness.metric_stream FINAL
FROM ingest.metric_stream FINAL
WHERE user_id = {userId:UUID}
AND provider_id = {providerId:String}
AND _peerdb_is_deleted = 0
AND is_deleted = 0
${recordFilter}
ORDER BY recorded_at DESC
LIMIT {limit:UInt32}
Expand Down
Loading
Loading