You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Collapses the three-mode require semantics into two, moves the
batch-declaration affordance to require instead of get_vars, and
renames require to ensure per @dunglas's concern that "require"
collides with PHP's language keyword (which takes a path).
- frankenphp_require_background_worker -> frankenphp_ensure_background_worker.
"Ensure" captures the "make sure this is running, start it if it isn't"
semantic without the keyword collision.
- Tolerant lazy-start inside frankenphp_handle_request: runtime ensure
now behaves the same as non-worker mode (lazy-start + timeout +
backoff tolerance). Bootstrap-before-handle_request keeps its
fail-fast discipline. This lets processes start only the workers
they actually exercise, instead of over-provisioning by pre-ensuring
everything that might be needed.
- Multi-name ensure: frankenphp_ensure_background_worker now accepts
string|array. Batch declaration with a shared deadline, fail-fast on
any worker's boot failure in bootstrap mode. get_vars loses the array
form, becoming single-name pure read.
- globalCtx.Done() wired into ensure's select cases, so in-flight
calls unblock cleanly on FrankenPHP shutdown instead of waiting
out their timeout.
- Fix: markBackgroundReady() is now called on every set_vars, not just
the first. Previously sk.readyOnce gated it, leaving isBootingScript
stuck at true after a crash-restart. That misclassified subsequent
crashes as boot failures and kept the readyWorkers metric decremented.
Copy file name to clipboardExpand all lines: docs/background-workers.md
+16-19Lines changed: 16 additions & 19 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ They observe their environment and publish variables that HTTP threads (both [wo
7
7
8
8
1. A background worker runs its own event loop (subscribe to Redis, watch files, poll an API...)
9
9
2. It calls `frankenphp_set_vars()` to publish a snapshot of key-value pairs
10
-
3. HTTP threads call `frankenphp_require_background_worker()` to declare a dependency and ensure the worker is running (lazy-started if needed, blocks until it has published at least once)
10
+
3. HTTP threads call `frankenphp_ensure_background_worker()` to declare a dependency and ensure the worker is running (lazy-started if needed, blocks until it has published at least once)
11
11
4. HTTP threads then call `frankenphp_get_vars()` to read the latest snapshot (pure read, no blocking)
12
12
13
13
## Configuration
@@ -27,59 +27,56 @@ example.com {
27
27
name feature-flags
28
28
}
29
29
30
-
# Catch-all - handles any unlisted name via require_background_worker()
30
+
# Catch-all - handles any unlisted name via ensure_background_worker()
31
31
worker /app/bin/console {
32
32
background
33
33
}
34
34
}
35
35
}
36
36
```
37
37
38
-
-**Named** (with `name`): lazy-started on first `require_background_worker()` call, or auto-started at boot if `num 1` is set.
38
+
-**Named** (with `name`): lazy-started on first `ensure_background_worker()` call, or auto-started at boot if `num 1` is set.
39
39
-**Catch-all** (no `name`): lazy-started on demand too, for any name not matched by a `name` directive. Use `max_threads` to cap how many can be created (defaults to 16). Not declaring a catch-all forbids unlisted names.
40
40
- Each `php_server` block has its own isolated scope - two blocks can use the same worker names without conflict.
41
41
-`max_consecutive_failures`, `env`, and `watch` work the same as HTTP workers.
Declares a dependency on a background worker. Behavior depends on the caller context:
47
+
Declares a dependency on one or more background workers. Pass a single name or an array of names for batch dependency declaration. The timeout applies across all names in a single call. Behavior depends on the caller context:
48
48
49
-
-**In an HTTP worker script, before `frankenphp_handle_request()` (bootstrap)**: lazy-starts the worker (at-most-once) if not already running, blocks until it has called `set_vars()` at least once. Fails fast on boot failure (no exponential-backoff tolerance): if the worker's first boot attempts fail, the exception is thrown right away with the captured details. Use this to declare dependencies up front.
50
-
-**In an HTTP worker script, inside `frankenphp_handle_request()` (runtime)**: assert-only. The worker must already be running (declared with `num 1` in Caddyfile or previously required during bootstrap). Never lazy-starts. Throws immediately if the name isn't known. Use this to assert a dependency without starting anything.
51
-
-**In non-worker mode (classic request-per-process)**: lazy-starts the worker and waits up to `$timeout`, tolerating transient boot failures via exponential backoff. The first request to a given name pays the startup cost; subsequent requests in the same FrankenPHP process see the worker already reserved and return almost immediately.
49
+
-**In an HTTP worker script, before `frankenphp_handle_request()` (bootstrap)**: lazy-starts the worker (at-most-once) if not already running, blocks until it has called `set_vars()` at least once. Fails fast on boot failure (no exponential-backoff tolerance): if the worker's first boot attempts fail, the exception is thrown right away with the captured details. Use this to declare dependencies up front so broken deps visibly fail the HTTP worker rather than let it serve degraded traffic.
50
+
-**Everywhere else (inside `frankenphp_handle_request()`, or classic request-per-process)**: lazy-starts the worker and waits up to `$timeout`, tolerating transient boot failures via exponential backoff. The first caller pays the startup cost; subsequent callers in the same FrankenPHP process see the worker already reserved and return almost immediately. This supports the common pattern of library code loaded after bootstrap declaring its own dependencies lazily.
- Throws `RuntimeException` on timeout, missing entrypoint, or boot failure. The exception contains the captured failure details when available: resolved entrypoint path, exit status, number of attempts, and the last PHP error (message, file, line).
67
66
- Pick a short `$timeout` (e.g. `1.0`) to fail fast; pick a longer one to tolerate slow/flaky startups.
- Throws `RuntimeException` if the worker isn't running or hasn't called `set_vars()` yet. Call `frankenphp_require_background_worker()` first to ensure readiness.
77
+
- Throws `RuntimeException` if the worker isn't running or hasn't called `set_vars()` yet. Call `frankenphp_ensure_background_worker()` first to ensure readiness.
82
78
- Within a single HTTP request, repeated calls with the same name return the same cached array, `===` comparisons are O(1).
79
+
- To read several workers, call `get_vars()` multiple times (each call is an O(1) lock-free read after the first per request).
The `frankenphp_require_background_worker`, `frankenphp_set_vars`, `frankenphp_get_vars`, and `frankenphp_get_worker_handle` functions are only exposed when FrankenPHP runs in SAPI mode (HTTP server). In CLI mode (`frankenphp php-cli ...`), they are hidden, so `function_exists()` returns `false`. Library code can rely on this to degrade gracefully:
222
+
In CLI mode (`frankenphp php-cli ...`), the frankenphp extension is not loaded, so `frankenphp_ensure_background_worker` and friends are absent. `function_exists()` returns `false`, allowing library code to degrade gracefully:
0 commit comments