data_updater_v2.issues
issues.py — the pieces every section’s issues are made of: one observation, its identity,
and the counts a monitoring receipt carries. Pure: the DataClient reads the tables and makes
the observations (universe_issues …), writes them (observe_issues) and records
the counts (record); the jobs decide when.
An observation is one mapping in the issue table’s words (tables/issues.py):
section the DataClient section (universe, daily ...)issue_type what it isseverity warning or errortable_name the table it concernslisting_id our listing id · global_id · symbol: who it concerns (None when nobody of ours)target_key the rest of its identity ({"date": ...})action the DataClient work that follows it (None: nothing to run)source the vendor it concerns, when oneevidence what was seen (never part of the identity)Its identity (issue_key) is the section, the kind, the table, who and the rest of the key:
seen again, the issue is the same one.
Functions
assessment_key
assessment_key(obs: Mapping[str, Any]) -> strThe identity a verdict on an observation’s target is kept under (no issue type).
fetch_failures
fetch_failures(section: str, table_name: str, gaps: Mapping[str, Mapping[str, Any]], rows: Iterable[Any] = ()) -> list[dict[str, Any]]The listings a build’s or an update’s fetch left unanswered (its gaps’ failed and
error), as observations for observe_issues — what no table can show afterwards:
no_source no source carries the listing ("no source carries it"): no action (a person, or the cleanup job through ``write_universe``'s ``fetch``)fetch_failed no source answered (error) — retrysource_failed a source did not answer while another did: the record stands on the others, a retry completes it — retryrows: the catalog rows the run was handed (they name who by our ids); a symbol not
among them is named by its symbol.
gap_findings
gap_findings(gaps: Mapping[str, Mapping[str, Any]]) -> list[dict[str, Any]]The counts a build’s or an update’s monitoring receipt carries from its gaps
(gaps.daily_bar_gaps … with failed): each key, how many listings it names —
error, empty and failed as errors, the rest warnings; owed and days
(counts and per-day logs) are no findings.
issue_key
issue_key(obs: Mapping[str, Any]) -> strAn observation’s identity: the same issue seen again has the same key.
observation
observation(section: str, issue_type: str, table_name: str, severity: str = 'warning', row: Any = None, symbol: str | None = None, target_key: Mapping[str, Any] | None = None, action: str | None = None, source: str | None = None, evidence: Mapping[str, Any] | None = None, listing_id: str | None = None, global_id: str | None = None) -> dict[str, Any]One observation; row (a catalog row) names who by our ids, else listing_id /
global_id / symbol as given.
split_change_observations
split_change_observations(changes: Iterable[Mapping[str, Any]], table_name: str) -> list[dict[str, Any]]What a fetch changed against the stored splits (events.split_changes), as
observations for observe_issues: split_changed per listing and day — action
rebuild_prices: the daily (and, in the job’s intraday set, the minutes) up to that
day rebuilt with the corrected splits. An announced change (a split not yet traded) asks
nothing: no stored price leans on it yet.
universe_findings
universe_findings(issues: Sequence[Mapping[str, Any]]) -> list[dict[str, Any]]The counts a section’s monitoring receipt carries: each issue type observed, by
severity (common-dagster’s finding_summary: grouped, never one row per ticker).