Area: streaming · query · sdk — bug (timestamp serialization inconsistency) · found via WaveHouse-Stats dogfooding
Expected: a DateTime column serializes identically on every read path — one unambiguous zoned RFC3339 form (…Z) — so a client stitching backfill (/v1/query) + live (/v1/stream) parses both on the same clock, and it matches the SSE frame's own received_timestamp.
Actual: the same event_ts (DateTime64(3,'UTC')) comes back two ways:
POST /v1/query → "event_ts":"2026-07-06T14:42:36Z" — RFC3339 Z.
GET /v1/stream frame → envelope "received_timestamp":"…Z" (zoned) but the wrapped row column "data":{…,"event_ts":"2026-07-06 14:42:36.000"} — ClickHouse-native (space separator, no zone). Same frame, envelope zoned / row column not.
The stream marshals the row data verbatim (internal/stream/hub.go project() → json.Marshal({… "data": evt.Data})), so a row DateTime keeps its native form, while /v1/query formats through the CH driver to RFC3339. The SDK SSETransport (clients/ts/src/stream/sse.js) passes data through untouched, and JS Date.parse reads a zone-less string as local time.
Impact: any SDK liveQuery consumer (backfill .fetch() + SSE live in one list) lands the two paths on different clocks — in America/New_York a live row's event_ts resolves +4h vs the same instant from /v1/query, sign-flipping by the viewer's UTC offset. Broke both ordering and the "N min ago" label in the Stats live feed (a 2-min-old event rendered "just now"). Every consumer must normalize today. Envelope-keyed logic (e.g. ingest latency off received_timestamp) is unaffected — the bug is row DateTime columns inside data.
Scope: render row DateTime/DateTime64 columns in the SSE data payload with the same formatter /v1/query uses (RFC3339 Z) rather than the driver-default YYYY-MM-DD HH:MM:SS.fff.
Related: #294 (SSE delivery path), #319 (stream-vs-query policy drift — same query/stream-parity theme), WaveHouse-Stats#55 (client-side workaround shipped there)
From WaveHouse-Stats WAVEHOUSE-FEEDBACK.md dogfooding (live curl capture + SDK-path analysis, dev 08c6f19); validated by code-read against ccd7549 (main) on 2026-07-06.
Area: streaming · query · sdk — bug (timestamp serialization inconsistency) · found via WaveHouse-Stats dogfooding
Expected: a
DateTimecolumn serializes identically on every read path — one unambiguous zoned RFC3339 form (…Z) — so a client stitching backfill (/v1/query) + live (/v1/stream) parses both on the same clock, and it matches the SSE frame's ownreceived_timestamp.Actual: the same
event_ts(DateTime64(3,'UTC')) comes back two ways:POST /v1/query→"event_ts":"2026-07-06T14:42:36Z"— RFC3339Z.GET /v1/streamframe → envelope"received_timestamp":"…Z"(zoned) but the wrapped row column"data":{…,"event_ts":"2026-07-06 14:42:36.000"}— ClickHouse-native (space separator, no zone). Same frame, envelope zoned / row column not.The stream marshals the row
dataverbatim (internal/stream/hub.goproject()→json.Marshal({… "data": evt.Data})), so a rowDateTimekeeps its native form, while/v1/queryformats through the CH driver to RFC3339. The SDKSSETransport(clients/ts/src/stream/sse.js) passesdatathrough untouched, and JSDate.parsereads a zone-less string as local time.Impact: any SDK
liveQueryconsumer (backfill.fetch()+ SSE live in one list) lands the two paths on different clocks — inAmerica/New_Yorka live row'sevent_tsresolves +4h vs the same instant from/v1/query, sign-flipping by the viewer's UTC offset. Broke both ordering and the "N min ago" label in the Stats live feed (a 2-min-old event rendered "just now"). Every consumer must normalize today. Envelope-keyed logic (e.g. ingest latency offreceived_timestamp) is unaffected — the bug is rowDateTimecolumns insidedata.Scope: render row
DateTime/DateTime64columns in the SSEdatapayload with the same formatter/v1/queryuses (RFC3339Z) rather than the driver-defaultYYYY-MM-DD HH:MM:SS.fff.Related: #294 (SSE delivery path), #319 (stream-vs-query policy drift — same query/stream-parity theme), WaveHouse-Stats#55 (client-side workaround shipped there)
From WaveHouse-Stats
WAVEHOUSE-FEEDBACK.mddogfooding (livecurlcapture + SDK-path analysis, dev08c6f19); validated by code-read againstccd7549(main) on 2026-07-06.