Skip to content

feat(cabq): cabq backfill implementation - #48

Merged
njones-icasa merged 10 commits into
mainfrom
ST2DAT-228-feat-cabq-CABQ-backfill-implementation
Sep 1, 2026
Merged

feat(cabq): cabq backfill implementation#48
njones-icasa merged 10 commits into
mainfrom
ST2DAT-228-feat-cabq-CABQ-backfill-implementation

Conversation

@njones-icasa

Copy link
Copy Markdown
Contributor

Why

This PR addresses the following problem / context:

  • Need backfill for CABQ source to enable re-fetching historical data.

How

Implementation summary - the following was changed / added / removed:

  • Implemented cabq/backfill.py.
  • Made changes to REST API calls in cabq/dlt_pipeline.py to query based on a time range.
  • Made changes to shared/backfill.py to enable a source to use different value types as location ids instead of just int.
  • Unit tests for the above.

Notes

Any special considerations, workarounds, or follow-up work to note?

  • None

@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Your pull request is automatically being deployed to Dagster Cloud.

Location Status Link Updated
aqueduct_dagster_defs_definitions View in Cloud Sep 01, 2026 at 07:37 PM (UTC)

"""
cfg = load_source_config("cabq")
client = build_cabq_client(cfg["api_base_url"])
try:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bare raise here is fragile and loses the underlying error info in the common case where _fetch_locations returns (None, err) without raising. In that case the bare raise produces RuntimeError: No active exception to reraise and err is discarded — confirmed by running it directly.

Minimal fix — fold the locations is None check into the same try, so the existing except Exception: client.close(); raise handles both cases (an actual raised exception, and this returned-None case) with one close() call instead of two, and the real err reason included:

try:
locations, err = _fetch_locations(client)
if locations is None:
raise RuntimeError(f"Backfill fetch failed to receive locations: {err}")
except Exception:
client.close()
raise

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adjusted the error logging as suggested

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good

def _fetch_readings() -> httpx.Response:
# query for location code = given location id for measurement info
return client.get(
query = (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CABQ's _fetch_readings_for_location builds the encoded query string by hand; hydrovu uses httpx's params (client.get(path, params=...)). This divergence is the issue — please switch CABQ to use params= for safety and consistency.

Note: tests/sources/cabq/test_dlt_pipeline.py assert the exact encoded URL string and will need to be updated to check parsed params (e.g. via httpx.URL(...).params) instead of raw string equality.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has been addressed, and I updated the call for fetch locations to do the same

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found and fixed one more issue in the params= migration — the query still joined clauses with a literal + (leftover from when the URL was hand-built), which params= now encodes as a literal %2B instead of a space. This broke every real query with a 400 from the API (and crashed with an unhandled KeyError: 'features' instead of a clean error, since the API returns HTTP 200 with an error body).

This wasn't backfill-only — _fetch_readings_for_location is also called from raw_cabq_readings, the daily production ingest asset, so this would have broken the daily pipeline too.

Fixed by joining clauses with real spaces instead of +.
Before merging this PR please Verify:

  • Direct call against the live API — returns real data, no more KeyError
  • Full cabq_backfill_refetch job run — succeeds
  • Full daily asset chain (raw_cabq_readings → canonical_bundles_cabq → frost_load_cabq) — succeeds end-to-end
  • Tests/ruff/mypy all clean

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, fair enough, honestly thought that the + was still needed. Tested the changes locally and can confirm that everything is working.

@likithabommasani21 likithabommasani21 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!
Verify all the CABQ pipelines works as excepted in dagster before merging

@njones-icasa
njones-icasa merged commit 9aa6e15 into main Sep 1, 2026
5 checks passed
@njones-icasa
njones-icasa deleted the ST2DAT-228-feat-cabq-CABQ-backfill-implementation branch September 1, 2026 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants