Skip to content

feat(dev-dump): record UDP for fm/f1, graceful shutdown, docs#58

Merged
Snazzie merged 16 commits intomainfrom
fix/dev-dump-scripts
Apr 18, 2026
Merged

feat(dev-dump): record UDP for fm/f1, graceful shutdown, docs#58
Snazzie merged 16 commits intomainfrom
fix/dev-dump-scripts

Conversation

@Snazzie
Copy link
Copy Markdown
Collaborator

@Snazzie Snazzie commented Apr 18, 2026

Summary

  • dev:dump:fm / dev:dump:f1 now actually produce .bin files. Previously they set a recordingGameId flag that went unused — wire a UdpRecorder into the listener so raw datagrams get appended, same directory and naming convention as the shared-memory recorders already use.
  • Recording is additive: live lap detection, DB writes, and WS broadcasts all keep running so the dashboard updates mid-recording.
  • Graceful shutdown: SIGINT/SIGTERM handlers flush all three recorders (UDP, ACC, AC-Evo) before process.exit so Ctrl+C produces a complete file instead of a zero-length one (Bun.file().writer() buffers internally).
  • New bun run gzip:recordings <path> script — gzips a single .bin in place (raw .bin is gitignored; commit the .bin.gz as a fixture).
  • Docs: docs/dev-recordings.md covers which script runs for which game, where files land, how to commit a recording as a fixture, and how to replay via the /dev import panel.

Test plan

  • bun run build clean
  • Manual: run bun run dev:dump:fm with FM sending UDP → test/artifacts/laps/fm-2023-*.bin exists, non-empty, Ctrl+C prints [UdpRecorder] Stopped. N packets written
  • Manual: drop that .bin into the /dev Import Dump panel → detects fm-2023, reports lap count
  • Same two steps for dev:dump:f1
  • bun run gzip:recordings path/to/foo.bin → produces foo.bin.gz next to it, keeps the raw

🤖 Generated with Claude Code

Snazzie and others added 16 commits April 18, 2026 18:21
dev:dump:fm and dev:dump:f1 previously only set a recordingGameId flag
that went unused — no .bin was produced. Wire a UdpRecorder into the
listener so these scripts now append raw datagrams to
test/artifacts/laps/{gameId}-{timestamp}.bin, matching the file layout
the shared-memory recorders (acc, ac-evo) already use.

Recording is additive: writePacket(buf) runs before parsePacket, so
live lap detection, DB writes, and WebSocket broadcasts to the
dashboard all keep working during a recording session. The /dev import
route auto-detects the gameId from the filename prefix and feeds the
dump through the full pipeline.

New docs/dev-recordings.md covers the end-to-end flow — which script
to run per game, where the .bin lands, and how to replay it via the
/dev Import Dump panel or the API.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Match the AccSharedMemoryReader pattern — pin recordingGameId once
before start(), let the listener open its .bin implicitly instead of
exposing a separate startRecording() toggle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All three recorders (UDP, ACC, AC-Evo) buffer writes through
Bun.file().writer(). Without a signal handler the default Ctrl+C path
exits before the buffer drains and .bin files end up zero-length or
tail-truncated.

Install a graceful-shutdown handler whenever recordingGameId is set —
it awaits stop() on every recorder in parallel before process.exit so
the file has a clean tail.

Also make UdpListener.stop() async and have restart() await it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Committed fixtures are the gzipped ones — raw .bin files from
`dev:dump:*` runs are developer-local.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Raw .bin dumps are gitignored — document the gzip -k flow so
contributors know how to land a new regression fixture.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Small bun script that walks test/artifacts/laps/ (or a single path) and
gzips every raw .bin in place, keeping the original next to the .gz.
Doc updated to point at the script.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Committing a recording should be deliberate — the script now errors
without a path argument instead of sweeping every raw .bin in the
default dir.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- parseDump takes (gameId, path) not just path — fix example
- Ctrl+C now flushes via SIGINT handler, update tip accordingly
- Dev URL is http://localhost:5173 (no portless/TLS)
- Rename gzip:recordings -> gzip:recording to match single-file scope

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ss --no-tls)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e spawning server + vite

- scripts/dev-proxy.ts: add --port 1355 so portless doesn't try to bind
  port 80 and request sudo
- package.json dev script: run dev:proxy sequentially before the
  concurrent server + vite pair, matching the dev:dump:* pattern

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Snazzie Snazzie merged commit 0ad962a into main Apr 18, 2026
1 check passed
@Snazzie Snazzie deleted the fix/dev-dump-scripts branch April 18, 2026 18:19
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