Repository navigation
refactor: 6-hourly collect-stats again; high-res samples from a run-anywhere sampler - #31
Conversation
…-stats back to 6-hourly collect-stats.yml returns to its plain 6-hourly schedule. collect-launch.yml samples every ~10 min (best effort) until WINDOW_END (2026-10-20), then runs 'gh workflow disable' on itself, so nothing keeps firing between launches.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
@greptileai review |
…h workflow Drop collect-launch.yml; collect-stats stays plain 6-hourly. sample_hf.py polls every 60 s with ETag conditional requests, appends change-only rows to data/hf/, resumes from the files, and --trim coarsens before submitting in a PR.
|
@greptileai review |
|
| - uses: actions/checkout@v4 | ||
| if: steps.window.outputs.open == 'true' |
There was a problem hiding this comment.
Queued collections lose samples
When both schedules fire at a six-hour boundary, one run can wait behind the other in collect-stats. Checkout without ref uses the run’s original SHA, not the latest master. If the first run pushes while the second waits, the second appends to an old copy of data/stats.csv. Its push is rejected, and git pull --rebase conflicts because both commits appended different rows at the same end of the file. That sample never reaches master.
The new second schedule makes this possible even when collection takes less than ten minutes. Set ref: master on both workflows’ checkouts so each run reads the latest files after it gets its turn.
There was a problem hiding this comment.
Moot: collect-launch.yml was removed in this PR (the sampler runs outside Actions), so only the 6-hourly collect-stats checks out and pushes.
There was a problem hiding this comment.
You’re right — this finding is moot. collect-launch.yml is not part of the current diff, and the only scheduled workflow now runs at 0 */6 * * *; the external sampler does not create a second Actions checkout/push race. No change is needed for this comment.
| with open(path, "w", newline="") as f: | ||
| w = csv.DictWriter(f, fieldnames=fields) | ||
| w.writeheader() | ||
| w.writerows(out) |
There was a problem hiding this comment.
Trimming can delete new samples
Running --trim while the sampler is collecting can silently delete samples. trim() reads the files, then truncates and rewrites them. Rows appended between those steps are lost, while the sampler still remembers their counts and skips writing them again. Use a shared lock for sampling and trimming, or refuse to trim while a sampler is active.
| until = ( | ||
| datetime.fromisoformat(args.until).replace(tzinfo=timezone.utc) | ||
| if args.until | ||
| else None |
There was a problem hiding this comment.
Time offsets change stopping time
--until silently changes the meaning of ISO times with an offset. 2026-10-20T02:00:00+02:00 means midnight UTC, but .replace(tzinfo=timezone.utc) makes it 02:00 UTC instead. Convert aware times with .astimezone(timezone.utc) and attach UTC only to times without an offset, or reject non-UTC offsets explicitly.
| args = p.parse_args() | ||
|
|
||
| if args.trim: | ||
| trim(args.trim) | ||
| return | ||
| token = os.getenv("GITHUB_TOKEN") | ||
| if not token and args.interval < 120: |
There was a problem hiding this comment.
| client = FakeClient(assets) | ||
| state = sample_hf.load_state() | ||
| assert sample_hf.sample_once(client, state) == (2, 1) | ||
| assert sample_hf.sample_once(client, state) == (0, 0) # nothing changed |
There was a problem hiding this comment.
The tests bypass ConditionalClient, and the trim test skips the assets file. Add mocked HTTP tests for a successful response followed by a 304, including cached next-page links. Also test trimming two different assets in the same bucket. The current tests cannot catch broken cached requests, skipped release pages, or dropped asset series.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
…ts to UTC, reject non-positive intervals; test client caching and per-asset trim
|
@greptileai review |
|
|
||
| import argparse | ||
| import csv | ||
| import fcntl |
There was a problem hiding this comment.
Sampler cannot start on Windows
The new unconditional import fcntl prevents sample_hf.py from starting on Windows. Python only provides fcntl on Unix, so Windows users get ModuleNotFoundError before they can sample, trim, or view help. This breaks the documented run-anywhere use. Use a cross-platform lock or provide a Windows locking branch.
There was a problem hiding this comment.
Fixed in 12c581e: msvcrt.locking on Windows, fcntl.flock elsewhere, imported lazily; test covers a second holder being refused.
|
@greptileai review |
|
@greptileai review |
|
@greptileai review |
Follow-up to #30, per Erik: no high-frequency Actions schedule at all.
collect-stats.ymlback to plain0 */6 * * *(removes feat: 10-minute stats during the v0.14.0 launch; exclude updater assets from totals #30's*/10cron and cadence step). Keeps feat: 10-minute stats during the v0.14.0 launch; exclude updater assets from totals #30's push-with-retry and the updater-asset exclusion.sample_hf.py: run it anywhere during a launch (laptop, server, VM), then submitdata/hf/*.csvin a PR. Polls every 60 s (--interval), with ETag conditional requests (unchanged responses are 304s, which don't count against the rate limit), and appends change-only rows in the same schemas asstats.csv/stats-assets.csv, so quiet minutes cost nothing. Downloads exclude updater assets likecollect_stats.downloads(). Resumes from the files after a restart;--untilstops it;--trim MINUTEScoarsens to the last row per series per bucket before submitting.