feat: declared background workers + frankenphp_get_worker_handle()#2398
feat: declared background workers + frankenphp_get_worker_handle()#2398nicolas-grekas wants to merge 1 commit intophp:mainfrom
Conversation
|
FYI I just did the split for now and didn't account for your last review on #2393 yet @AlliBalliBaba I woke with this idea for the next step: My app-declares-the-sidekicks requirement could be achieved with a protocol that wouldn't require adding the in my current proposal we have this: # Catch-all bg worker, instantiated lazily by ensure(name)
worker bin/jobs.php {
background
max_threads 16
}what we could do is: on bootstrap of frankenphp, we run |
|
What's the benefit over the Caddyfile/JSON config we already have? For the record, what you want to achieve is already possible: any PHP script, including workers, can call the Caddy REST API to dynamically tweak the FrankenPHP/Caddy config. It would be nice to add an example showing how to do that btw. |
|
I didn't know, worth checking if we can use that to let the PHP app start new bgworkers then. Feels strange at first that the app can do that - reconfigure itself. I'd be happy to know more about this and demo it. |
I don't know, it sounds hacky to me and we'd still need to implement calling a script and parsing the output. Perhaps we can just start without lazy starts first? My feeling is still that lazy starting doesn't offer any benefit without also auto-scaling down, so I'd be in favour of just shipping background workers at first. We can see how things go and implement general worker orchestration in the php bridge later when we get to task workers. |
5b2e8cd to
46d1a02
Compare
{"name":"blub","file_name":"/app/blub.php","num":1} |
|
And how does this behave? I mean: what does this restart? all the HTTP app? How about failures? etc - any link to doc if there is one somewhere? |
Adds a minimal background-worker surface: long-lived non-HTTP PHP scripts declared via WithWorkerBackground() / `background` in the Caddyfile worker block. Each worker exposes a stop-pipe stream via frankenphp_get_worker_handle(); on FrankenPHP shutdown / restart Go closes the write end so the script's stream_select returns EOF and the loop can exit cleanly. Crash-restart with quadratic backoff, halted by max_consecutive_failures. Per-php_server scope isolation so two server blocks can declare the same worker name without colliding. Deferred to follow-ups (kept out for review surface): - frankenphp_ensure_background_worker() / lazy-start machinery - Catch-all (empty-name) workers - Shared-state APIs (frankenphp_set_vars / frankenphp_get_vars) What lands: - frankenphp_get_worker_handle() zif + stop-fd plumbing in C - WithWorkerBackground() / WithWorkerScope() Go options; num >= 1 required - backgroundWorkerThread handler: boot, restart with backoff, cap-on-crash, graceful exit on stop-fd close - Per-scope lookup map keyed by user-facing name - Caddy `background` worker flag + scope-label cascade (host matcher -> first listener address) so the metric prefix m#<scope-label>:<name> is set before the very first metric emit. Tests: - TestBackgroundWorkerLifecycle: bg worker boots, touches sentinel, parks, exits within 10s of Shutdown. - TestBackgroundWorkerCrashRestarts: exit(1) -> respawn -> restarted sentinel. - TestBackgroundWorkerWithoutHTTP: a regular HTTP request alongside a bg worker still serves. - TestBackgroundWorkerSameNameDifferentScope: two servers each declare "shared", both run, distinct *worker per scope.
46d1a02 to
bd245bf
Compare
|
Oh that's to add a worker at runtime. It uses the json format and post appends, patch updates: https://caddyserver.com/docs/api (and no, it shouldn't be used for this, the application shouldn't have to rely on the admin endpoint being up) |
Summary
Smallest useful slice of the background-worker work. Adds long-lived
non-HTTP PHP scripts declared via
WithWorkerBackground()/backgroundin the Caddyfile worker block, plus the
frankenphp_get_worker_handle()primitive that gives the script a stream it can park on (
stream_select)to exit gracefully on shutdown / restart.
This carves the minimal surface out of the larger PR #2393 so it is small
enough to review and merge on its own. The richer features built on top
of these primitives are deferred to follow-ups.
What's in
frankenphp_get_worker_handle(): resource— closes whenFrankenPHP drains the worker (write end of the stop pipe is closed Go-side).
WithWorkerBackground(),WithWorkerScope(),NextScope,SetScopeLabel.num >= 1is required for bg workers (no lazy-startin this build).
halt respawn at
max_consecutive_failures. Exit-status 0 = cooperativerestart, no failure counted.
backgroundflag insidephp_server { workers ... }.Per-php_server scope isolation so two server blocks can declare the same
worker name without colliding. Scope label resolved before
Initvia thecascade in
caddy/scopelabel.go(host matcher → first listener address)so the very first metric emit on every bg worker carries the right
m#<scope-label>:<name>prefix.Deferred (kept out for review surface)
frankenphp_ensure_background_worker()and the lazy-start / readiness/ boot-failure machinery it pulls in.
frankenphp_set_vars/frankenphp_get_vars).Test plan
TestBackgroundWorkerLifecycle— bg worker boots, touches sentinel,parks on stop pipe,
Shutdown()returns within 10s.TestBackgroundWorkerCrashRestarts—exit(1)on first boot,respawned thread runs the success branch.
TestBackgroundWorkerWithoutHTTP— bg worker doesn't interceptHTTP traffic; a regular request still serves.
TestBackgroundWorkerSameNameDifferentScope(internal) — twophp_server scopes each declare "shared", both Init successfully and
run independently.
TestNextScopeIsDistinct.