feat: declared background workers + frankenphp_get_worker_handle() - #2617
Open
nicolas-grekas wants to merge 1 commit into
Open
feat: declared background workers + frankenphp_get_worker_handle()#2617nicolas-grekas wants to merge 1 commit into
nicolas-grekas wants to merge 1 commit into
Conversation
Background workers are long-lived non-HTTP PHP scripts declared via WithWorkerBackground() or the `background` flag in Caddyfile worker blocks. The script runs in a loop: it is re-run on cooperative exit (status 0) and restarted with a quadratic backoff on crash, failing hard on max_consecutive_failures during startup only. frankenphp_get_worker_handle() returns a stream over the read end of a per-thread stop pipe; draining the thread (shutdown, reboot, handler transition) closes the write end, so a script parked in stream_select wakes up and can exit gracefully. Background workers attach to a Server through the existing WithWorkerServerScope(); their name is mandatory (it is the script's identity, exposed as FRANKENPHP_WORKER) and lives in the global worker namespace, which the Caddy module already qualifies per server.
5 tasks
Contributor
|
Please rewrite the PR description to not be LLM slop reasoning with itself about what it did and why. I've tried reading this three times and I just can't. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reopens #2543, which GitHub auto-closed when #2499 merged and
refactor/phpserverwas deleted. The base branch is gone, so #2543 itself can no longer be reopened or retargeted; this is the same single commit rebased ontomain. Supersedes #2398.A worker declared with
WithWorkerBackground()/backgroundin the Caddyfile runs its script in a loop outside the HTTP request cycle. Thefrankenphp_get_worker_handle()primitive hands the script a stream that reaches EOF when FrankenPHP drains the worker, so it can park onstream_select()and exit gracefully on shutdown, reboot or restart.What's in
frankenphp_get_worker_handle(): resource, closes when the worker is drained (the Go side closes the write end of a per-thread stop pipe).WithWorkerBackground(). Background workers attach to aServerthroughWithWorkerServerScope();num >= 1is required (no lazy-start in this build) and the name is mandatory since it is the script's identity ($_SERVER['FRANKENPHP_WORKER']).backgroundWorkerThreadimplementsthreadHandlerand mirrorsworkerThread's state machine: boot, re-run on cooperative exit (status 0, backoff reset), crash-restart with quadratic backoff, hard failure onmax_consecutive_failuresduring startup only.backgroundflag inside worker blocks (php_server and global).nameis required,matchis rejected. Metrics and logs use the worker name, which the server-qualified naming already keeps unique acrossphp_serverblocks, so two blocks can declare the same worker name.Rebase onto main
The commit is unchanged in substance. Four adjustments were needed against current
main:toWorkerOptions()gainedopts = append(opts, wc.options...)in fix: review follow-ups on the php_server refactor聽#2565; the newWithWorkerBackground()is appended alongside it rather than replacing it.newWorker()'s global-filename check was restructured by fix: review follow-ups on the php_server refactor聽#2565 into ao.server == nilblock that also rejects unscoped request matchers. The background exemption is now nested inside it: background workers are keyed by name and stay out ofglobalWorkersByPath, so several may share one script. The background validation still runs earlier in the function, so a background worker with a matcher keeps its own "cannot match requests" error rather than falling through to the unscoped-matcher one.frankenphp_opcache_restart_hook()and thezend_accel_schedule_restart_hookwiring were removed fromfrankenphp.con main; the conflict only carried them as context, so they are not reintroduced.NewServer()is nowNewServer(root string, options ...ServerOption), sobgworker_test.gousesWithServerName()/WithServerEnv().drain()is still wired intothread.shutdown()andrebootAllThreads(), so shutdowns and watch-triggered reboots wake parked background workers instead of hitting the force-kill grace period.Deferred (kept out for review surface)
frankenphp_ensure_background_worker()and lazy-start machinery.frankenphp_set_vars/frankenphp_get_vars).frankenphp_start_background_worker()runtime API (discussed in feat: declared background workers + frankenphp_get_worker_handle()聽#2398); the primitives here are compatible with it.Test plan
TestBackgroundWorkerLifecycle: bg worker boots, touches sentinel, parks on the stop pipe,Shutdown()returns within 10s.TestBackgroundWorkerCrashRestarts:exit(1)on first boot, the respawned run touches the "restarted" sentinel.TestBackgroundWorkerOnServer: server-scoped worker inherits the server env,FRANKENPHP_WORKERcarries the name, HTTP requests on the same server still serve.TestBackgroundWorkerValidation: name required,num >= 1, global name namespace, request matchers rejected.TestWorkerBackgroundConfig/RequiresName/RejectsMatch(Caddyfile parsing).Both modules pass
go vetincluding test files,go buildcompiles the C side, andfrankenphp.cis clang-format clean. The runtime tests need CI: on my box (WSL2) per-thread engine bootstrap of an embed ZTS build is pathologically slow and linking needs dev libs I do not have, so everyInit()-based test is unrunnable locally, including on unmodified base commits.