Skip to content

fix(server): route HTTP-submitted job logs into the per-job file#133

Merged
Sootopolis merged 1 commit into
mainfrom
fix/job-logger-inheritance
Jun 26, 2026
Merged

fix(server): route HTTP-submitted job logs into the per-job file#133
Sootopolis merged 1 commit into
mainfrom
fix/job-logger-inheritance

Conversation

@Sootopolis

Copy link
Copy Markdown
Owner

What

HTTP-submitted jobs (every ccas <cmd> CLI call → POST /api/jobs/*) wrote an empty per-job log (${JOB_LOGS_DIR}/<id>.log), so the CLI's log follow showed nothing after <slug> submitted: <id>.

Root cause: JobRunner.submit forks each job with .forkIn(layerScope); the forked fiber inherits currentLoggers from the submitting fiber. zio-http request handlers run outside ProgressDisplay's withLoggerScoped tree, so they carry only the default logger — the job logged via the default logger and asZLogger (the only logger that writes the per-job FileSink) never fired. Scheduler-submitted jobs (ClubData/MatchRef) were unaffected because the scheduler fiber is inside the scope — which is why this only surfaced for membership after #130 made it actually log.

  • ProgressDisplay.installLoggerremoveDefaultLoggers + withLoggerScoped(asZLogger), applied inline; forces {asZLogger} onto the wrapped effect and its forked children.
  • JobRunner.submit wraps every job with display.installLogger(...), so HTTP- and scheduler-submitted jobs log identically. .ensuring finalizer extracted as a named release; *> chains converted to for-comprehensions.

Fixes

Closes #132 (follow-up to #129/#130)

Testing

🤖 Generated with Claude Code

https://claude.ai/code/session_01ETHm6wCYdzFuB3kNEBayjF

JobRunner.submit forks each job with `.forkIn(layerScope)`, so the job
inherits `currentLoggers` from the submitting fiber. zio-http request
handlers (every `ccas <cmd>` CLI call) run outside ProgressDisplay's
`withLoggerScoped` tree, carrying only the default logger — so the job
logged via the default logger and `asZLogger` never wrote the per-job
FileSink. The file stayed empty, so the CLI's log follow showed nothing
after "<slug> submitted: <id>". Scheduler-submitted jobs were fine (their
fiber is inside the scope), which is why this only surfaced for membership
after #130 made it actually log.

Add ProgressDisplay.installLogger (removeDefaultLoggers +
withLoggerScoped(asZLogger)) and wrap every job with it in
JobRunner.submit, so a job logs through asZLogger into its per-job file
regardless of which fiber submitted it. HTTP- and scheduler-submitted jobs
now log identically.

TestJobRunner's shared layer switches from ProgressDisplay.live to
ProgressDisplay.make (no ambient logger), reproducing the HTTP
default-logger context; its three per-job-log assertions fail without the
fix and pass with it.

Closes #132

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ETHm6wCYdzFuB3kNEBayjF
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.

HTTP-submitted jobs write empty per-job logs — JobRunner forks inherit the request handler's default logger, not ProgressDisplay's

1 participant