Stream retention guard
What this is
CDF Records streams delete data after settings.lifecycle.dataDeletedAfter. Some validation surfaces only write a complete run on DataProduct/RuleSet version change (instance historic, edge existence baseline) or only rewrite the current SHACL window (timeseries). The stream retention guard re-triggers those complete runs before the last qualifying jobRunId expires.
When to use it
Leave the guard on (default) when operators query Records for a full historic snapshot, an estate-wide edge baseline, or a complete current-window timeseries run — and the stream is not unlimited.
Turn a surface off with ensure_complete_run_in_stream: false on the view YAML, timeseries YAML, or (for edge rules) the stored EdgeExistenceRuleState flag.
Uniqueness is not in this guard: the dedicated uniqueness cron already posts a complete aggregate pass. RAW, sync-cursor instance runs, and incremental edge_existence_event records are also out of scope.
User mental model
- Deploy writes stored payloads and
ensure_complete_run_in_stream(default true) onto DMS state nodes. dq-stream-retention-guardruns once per night in 01:00–04:59 UTC, with the minute/hour jittered bysha256(COGNITE_PROJECT) % 240so tenants on a shared cluster are not all refreshing at:00.- Each cycle:
GET /streams/{id}fordataDeletedAfter(never YAML), then RecordsuniqueValuesonjobRunId, then refresh surfaces that would expire withinstream_retention_lead_time(defaultP1D). - Instance historic is re-queued on the same DataProduct/RuleSet version (
hq_{view}_retention). Timeseries and edge baseline arefunctions.callwith a freshjob_run_id.
Runtime behavior
What is refreshed
| Surface | Refresh | Notes |
|---|---|---|
| Instance historic | HistoricJobQueue hq_{view}_retention |
Same version must not block. historic_reprocess_on_update: false does not apply. Skip only if that view already has a queued or running HQ job. |
| Edge existence baseline | edge_existence_baseline |
Modeling triggers are incremental (edge existence). Completeness requires a finished baseline (jobRunId plus pagination cleared), not recent event records. |
| Timeseries | Normal-mode validation_type: timeseries |
One complete current window for the config. Does not set backfill.enabled. A P7D stream cannot keep a 30-day backfill corpus. |
Detection
Retention period is always GET /streams/{id} → settings.lifecycle.dataDeletedAfter. Missing value → unlimited → skip. Streams API errors → print a warning and skip that cycle.
Latest run start comes from Records aggregate uniqueValues on jobRunId (filter ruleSetId + ruleSetVersion, size 2000), then prefix-filtered per surface. Instance historic completeness uses job_{view}_{epoch} from the historic orchestrator (build_historic_job_run_id). hq_* strings are HistoricJobQueue node ids and are not Records jobRunIds. Uniqueness ids (job_{view}_uniqueness_{epoch}) are excluded from instance historic matching. See Records output.
uniqueValues is typically count top-N, not recency. Distinct jobRunIds that share the same ruleSetId/ruleSetVersion (uniqueness, incidental windows, many historic ids) compete for those 2000 buckets. A recent low-count historic id can fall out of the window and look like “no qualifying run.” v1 does not page beyond this cap.
Refresh when now >= run_start + retention - lead_time, or when there is no qualifying complete run. Timeseries and edge baseline also skip when the last retention functions.call is still Running, or when a refresh was triggered within lead_time. Edge completeness prefers a finished edge_{rule}_{epoch} over a newer sibling job_{view}_{epoch} that has no pagination row for that rule. An existing pagination node with a cleared cursor (including processed_count == 0) is complete; a missing node is not.
Schedule
- Night window: 01:00–04:59 UTC (240 minute slots).
- Default cron:
{minute} {hour} * * *fromsha256(project) % 240. - YAML
stream_retention_guard_cronwins when set. - Missing project name →
14 2 * * *(not:00). - Deploy prints the resolved expression and persists it on
DataQualitySettings.
This is not a sleep inside the function. CDF workflow crons are fixed at deploy.
Settings (YAML)
# settings.yaml
stream_retention_lead_time: P1D # optional; default P1D
stream_retention_guard_cron: "30 3 * * *" # optional override
# views/my_view.yaml or timeseries/my_sensors.yaml
ensure_complete_run_in_stream: true # default; set false to opt out
Timeseries backfill
v1 re-triggers normal mode only. Older backfill windows still expire with the stream. Full backfill replay is out of scope.
Limitations
- Does not make history longer than stream retention (records streams).
- Writing the same results to a second Records stream is not available yet.
- Size
stream_retention_lead_timefor HistoricJobQueue wait p99 plus historic run p99, or a same-version refresh can miss the expiry window. - Multi-DataProduct views share one
ViewConfigStatenode ({view_space}__{view_external_id}); last deploy/sync payload wins. - Records
uniqueValuesonjobRunIdusessize: 2000(count top-N). Very large numbers of distinct ids for one RuleSet can hide a recent historic run.