Skip to content

perf: move log receiver processing to a worker thread#617

Draft
garrappachc wants to merge 4 commits into
masterfrom
feat/log-receiver-worker-thread
Draft

perf: move log receiver processing to a worker thread#617
garrappachc wants to merge 4 commits into
masterfrom
feat/log-receiver-worker-thread

Conversation

@garrappachc
Copy link
Copy Markdown
Member

Summary

  • UDP parsing, regex game-event matching, and MongoDB log writes now run on a dedicated node:worker_threads worker with its own MongoClient and a second OTEL SDK instance for metrics
  • The worker uses per-event keyword pre-filters (String.includes) before attempting regex matches, skipping >90% of log lines (e.g. shot_fired, damage, picked up item) with near-zero cost
  • The main event loop now only calls events.emit() when the worker posts a matched game event via postMessage — it does zero work per log line otherwise
  • Graceful shutdown: main thread sends a ControlMessage to the worker on app close; worker drains, closes the socket/MongoDB, shuts down OTEL, then exits

Motivation

During active games the log receiver was causing p99 event loop delay spikes (up to ~20ms). A sample game log had ~21k lines, of which ~19k were high-frequency noise events that still triggered 13 synchronous regex checks each on the main thread.

Test plan

  • Run pnpm test — all existing tests pass
  • Start dev server with a real MongoDB instance and verify log receiver worker starts (log receiver worker listening at ... in stdout)
  • Run a game and confirm game events (round start/end, player connect, scores) are processed correctly
  • Verify OTEL metrics for tf2pickup.log_receiver.message.count and tf2pickup.games.events.count still appear in Grafana

🤖 Generated with Claude Code

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 18, 2026

Playwright test results

passed  199 passed

Details

stats  199 tests across 29 suites
duration  8 minutes, 59 seconds
commit  c2b1c5f

garrappachc and others added 2 commits May 21, 2026 15:54
UDP parsing, regex game-event matching, and MongoDB log writes now run
on a dedicated worker thread (node:worker_threads) with its own
MongoClient and a second OTEL SDK instance for metrics. The main event
loop only calls events.emit() when the worker posts a matched game event
via postMessage, eliminating per-log-line synchronous work from the
main thread.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@garrappachc garrappachc force-pushed the feat/log-receiver-worker-thread branch from b41fa35 to ba97136 Compare May 21, 2026 13:54
garrappachc and others added 2 commits May 21, 2026 16:05
Add `log_receiver.use_worker_thread` boolean config (default: false) so
the worker thread path can be tested per-deployment before rolling out
globally. Restores the original inline UDP + gamelog:message path as the
default. Also fixes pre-existing lint errors in worker-message.ts and
log-receiver.worker.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ver worker

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant