|
23 | 23 | use Symfony\Component\HttpKernel\HttpKernelInterface;
|
24 | 24 | use Symfony\Component\Runtime\Internal\MissingDotenv;
|
25 | 25 | use Symfony\Component\Runtime\Internal\SymfonyErrorHandler;
|
| 26 | +use Symfony\Component\Runtime\Runner\FrankenPhpWorkerRunner; |
26 | 27 | use Symfony\Component\Runtime\Runner\Symfony\ConsoleApplicationRunner;
|
27 | 28 | use Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner;
|
28 | 29 | use Symfony\Component\Runtime\Runner\Symfony\ResponseRunner;
|
@@ -42,6 +43,7 @@ class_exists(MissingDotenv::class, false) || class_exists(Dotenv::class) || clas
|
42 | 43 | * - "use_putenv" to tell Dotenv to set env vars using putenv() (NOT RECOMMENDED.)
|
43 | 44 | * - "dotenv_overload" to tell Dotenv to override existing vars
|
44 | 45 | * - "dotenv_extra_paths" to define a list of additional dot-env files
|
| 46 | +* - "worker_loop_max" to define the number of requests after which the worker must restart to prevent memory s |
45 | 47 | *
|
46 | 48 | * When the "debug" / "env" options are not defined, they will fallback to the
|
47 | 49 | * "APP_DEBUG" / "APP_ENV" environment variables, and to the "--env|-e" / "--no-debug"
|
@@ -73,7 +75,7 @@ class SymfonyRuntime extends GenericRuntime
|
73 | 75 | private readonly Command $command;
|
74 | 76 |
|
75 | 77 | /**
|
76 |
| -* @param array { |
| 78 | +* @param array{ |
77 | 79 | * debug?: ?bool,
|
78 | 80 | * env?: ?string,
|
79 | 81 | * disable_dotenv?: ?bool,
|
@@ -88,6 +90,7 @@ class SymfonyRuntime extends GenericRuntime
|
88 | 90 | * debug_var_name?: string,
|
89 | 91 | * dotenv_overload?: ?bool,
|
90 | 92 | * dotenv_extra_paths?: ?string[],
|
| 93 | +* worker_loop_max?: int, // Use 0 or a negative integer to never restart the worker. Default: 500 |
91 | 94 | * } $options
|
92 | 95 | */
|
93 | 96 | public function __construct(array $options = [])
|
@@ -143,12 +146,23 @@ public function __construct(array $options = [])
|
143 | 146 |
|
144 | 147 | $options['error_handler'] ??= SymfonyErrorHandler::class;
|
145 | 148 |
|
| 149 | +$workerLoopMax = $options['worker_loop_max'] ?? $_SERVER['FRANKENPHP_LOOP_MAX'] ?? $_ENV['FRANKENPHP_LOOP_MAX'] ?? null; |
| 150 | +if (null !== $workerLoopMax && null === filter_var($workerLoopMax, \FILTER_VALIDATE_INT, \FILTER_NULL_ON_FAILURE)) { |
| 151 | +throw new \LogicException(\sprintf('The "worker_loop_max" runtime option must be an integer, "%s" given.', get_debug_type($workerLoopMax))); |
| 152 | +} |
| 153 | + |
| 154 | +$options['worker_loop_max'] = (int) ($workerLoopMax ?? 500); |
| 155 | + |
146 | 156 | parent::__construct($options);
|
147 | 157 | }
|
148 | 158 |
|
149 | 159 | public function getRunner(?object $application): RunnerInterface
|
150 | 160 | {
|
151 | 161 | if ($application instanceof HttpKernelInterface) {
|
| 162 | +if ($_SERVER['FRANKENPHP_WORKER'] ?? false) { |
| 163 | +return new FrankenPhpWorkerRunner($application, $this->options['worker_loop_max']); |
| 164 | +} |
| 165 | + |
152 | 166 | return new HttpKernelRunner($application, Request::createFromGlobals(), $this->options['debug'] ?? false);
|
153 | 167 | }
|
154 | 168 |
|
|
0 commit comments