Skip to content

fix: retry transient failures in the weekly online fixture refresh - #188

Merged
kevincostner17 merged 1 commit into
mainfrom
fix/resilient-fixture-fetch
Sep 14, 2026
Merged

kevincostner17 merged 1 commit into
mainfrom
fix/resilient-fixture-fetch

Conversation

@kevincostner17

Copy link
Copy Markdown
Contributor

Summary

The scheduled Refresh online fixtures workflow has failed three weeks running (08-31, 09-07, 09-14). The 09-14 run died on:

http.client.RemoteDisconnected: Remote end closed connection without response

_download made a single urlopen call with no retry. RemoteDisconnected (and IncompleteRead) subclass HTTPException/OSError, not URLError, so the per-dataset except didn't catch them. One dropped connection from archive.ics.uci.edu aborted the entire run, and every remaining dataset was skipped. Caught failures (e.g. the 08-31 Connection reset by peer) also turned the job red, because any single failure exited 1.

Changes

  • scripts/fixture_download.py (new): download() retries OSError/HTTPException, HTTP 429 and 5xx with exponential backoff and jitter (4 attempts). Permanent 4xx errors are raised immediately; once retries run out it raises TransientFetchError.
  • scripts/fetch_online_fixtures.py:
    • Continues past a failed dataset.
    • Classifies each failure as either network (retries exhausted) or dataset (parse error, empty after parse, hash mismatch, permanent HTTP error).
    • New --max-failures N sets how many network failures are tolerated (default 0). Dataset failures always fail the run.
    • A network failure keeps the dataset's existing manifest entry.
    • Emits ::warning:: annotations under GitHub Actions.
  • tests/expectations.py: the live-fetch helper reuses download().
  • .github/workflows/fetch-fixtures.yml:
    • Runs with --max-failures 2.
    • The offline verify step now uses if: always() and -m "not online"; the live fetch already ran in the previous step.
    • Adds a 30-minute timeout.
    • Opens or updates a nightly-failure issue on scheduled failures, like the other nightly lanes.

Tests

New tests/test_fixture_download.py (11 tests, no network):

  • retries on RemoteDisconnected and connection reset, with backoff
  • gives up after N attempts
  • retries 429/503; doesn't retry 404
  • main() keeps going after a network failure and respects the budget
  • parse, permanent-HTTP and empty-after-parse failures are never tolerated
  • warning annotations under GitHub Actions

Results:

  • pytest tests/test_fixture_download.py: 11 passed
  • pytest tests/test_online_datasets.py -m "not online": 170 passed
  • ruff check on the changed files: clean

The weekly "Refresh online fixtures" workflow failed three weeks running.
_download had no retries, and http.client.RemoteDisconnected is not a
URLError, so a single dropped connection from archive.ics.uci.edu escaped
the per-dataset handler and aborted the whole run.

- scripts/fixture_download.py: shared download() with exponential backoff
  for OSError/HTTPException, 429 and 5xx; permanent 4xx raise immediately.
- fetch_online_fixtures.py: continue per dataset, separate network failures
  from dataset (parse/empty/hash/permanent HTTP) failures, add
  --max-failures for the network budget, emit GitHub warning annotations.
- tests/expectations.py: the live-fetch helper reuses download().
- fetch-fixtures.yml: --max-failures 2, always run the offline verify step
  with -m "not online", open a nightly-failure issue on scheduled failures.
@coderabbitai

coderabbitai Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: abcdf968-b521-43c0-a179-7c563f993e86


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kevincostner17
kevincostner17 merged commit e27bea4 into main Sep 14, 2026
14 of 15 checks passed
kevincostner17 added a commit that referenced this pull request Sep 14, 2026
test-matrix (3.9) has failed on main since #187: with pandas 1.5, the
streaming state converted numeric columns via
pd.to_numeric(s).to_numpy(dtype="float64"), which raises "cannot convert to
'float64'-dtype NumPy array with missing values" for nullable (masked)
integer columns with NA. fd.clean_timeseries and StreamingCleaner hit it on
any Int*/UInt* column with gaps.

Pass na_value=np.nan there and in the time-series interpolation helper,
which has the same conversion. Also pin the alert step #188 added to
fetch-fixtures.yml, which #190's SHA sweep predated.
@kevincostner17
kevincostner17 deleted the fix/resilient-fixture-fetch branch September 14, 2026 18:58
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.

1 participant