Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.x] Add support for FrankenPHP #764

Merged
merged 83 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
5e13fa8
Add support for FrankenPHP
dunglas Oct 10, 2023
c16125e
make linters happy
dunglas Oct 26, 2023
f560ebf
Update src/Commands/StatusCommand.php
dunglas Oct 26, 2023
a8a7ea4
use a static closure in the worker script
dunglas Oct 28, 2023
7b8200d
tabs
dunglas Oct 28, 2023
fe0f691
tabs
dunglas Oct 28, 2023
6c90b98
tabs
dunglas Oct 28, 2023
0432d92
tabs
dunglas Oct 28, 2023
d74e7f8
use match
dunglas Oct 28, 2023
b0021b7
fix vuln and simplify config
dunglas Oct 28, 2023
531d43c
cs
dunglas Oct 28, 2023
6c47901
@francislavoie review
dunglas Oct 28, 2023
7616f43
Update StartFrankenPhpCommand.php
dunglas Oct 28, 2023
235cb48
Update frankenphp-worker.php
dunglas Oct 28, 2023
7042db6
Update InstallCommand.php
dunglas Oct 28, 2023
4e30c2a
docs: update README and composer.json
dunglas Oct 30, 2023
8a36beb
cs
dunglas Oct 30, 2023
cf9e3a8
phpstan
dunglas Oct 30, 2023
5eb9871
simplify
dunglas Oct 30, 2023
7654199
cs
dunglas Oct 30, 2023
10d2d29
better Caddyfile
dunglas Oct 30, 2023
1ca92c4
Update octane.php
dunglas Nov 1, 2023
dfcae59
fix error handling
dunglas Nov 19, 2023
05f10ab
Merge branch 'feat/frankenphp' of github.com:dunglas/octane into feat…
dunglas Nov 19, 2023
0564dae
disable debug mode as it's slow
dunglas Nov 19, 2023
523c6c4
Fix swoole and octane write server running
nunomaduro Nov 20, 2023
574fe87
fix: ignore user abort
dunglas Nov 22, 2023
81fa352
feat: download the stable version
dunglas Dec 10, 2023
7ec5e46
follow symlinks
dunglas Dec 10, 2023
e36cac6
improve perf
dunglas Dec 10, 2023
4f275f8
fix non-tty mode
dunglas Dec 10, 2023
82088b7
formatting
taylorotwell Dec 13, 2023
ad53742
formatting
taylorotwell Dec 13, 2023
6d4af1e
formatting
taylorotwell Dec 13, 2023
799df5b
formatting
taylorotwell Dec 13, 2023
7198e80
formatting
taylorotwell Dec 13, 2023
16ae754
formatting
taylorotwell Dec 13, 2023
bf67790
performance
taylorotwell Dec 13, 2023
267d9fa
fix log level support
dunglas Dec 13, 2023
67d1112
more robust log level handling in Mercure block
dunglas Dec 13, 2023
e6c032a
fix logs
dunglas Dec 13, 2023
50d1fae
better logging handling
dunglas Dec 13, 2023
8f4da9c
cs
dunglas Dec 13, 2023
a024e85
cs
dunglas Dec 13, 2023
f14179d
missing changes in Caddyfile
dunglas Dec 13, 2023
fa3a3d2
Updates changelog
nunomaduro Dec 14, 2023
1917eb8
Prettify output
nunomaduro Dec 14, 2023
f091feb
cs
nunomaduro Dec 14, 2023
f37194b
Displays regular error messages
nunomaduro Dec 14, 2023
15b2447
Ensures binary is up-to-date
nunomaduro Dec 14, 2023
6775ba2
Ensures binary is up-to-date
nunomaduro Dec 14, 2023
ee5142a
Removes mercure
nunomaduro Dec 14, 2023
b33b7d1
Removes unused warning
nunomaduro Dec 14, 2023
9972b38
Publishes only a simple require
nunomaduro Dec 14, 2023
309caed
Style
nunomaduro Dec 14, 2023
fd56077
Cleans up code
nunomaduro Dec 14, 2023
d6547ed
Uses `--caddyfile`
nunomaduro Dec 14, 2023
ed6441c
Fixes catch
nunomaduro Dec 14, 2023
b9d8575
formatting
taylorotwell Dec 14, 2023
e9d9ba6
Fixes log output
nunomaduro Dec 15, 2023
61ab3c1
Fix bug
nunomaduro Dec 15, 2023
af34f43
Removes non-needed comments
nunomaduro Dec 15, 2023
3740c0e
Prefixes caddy environment variables
nunomaduro Dec 15, 2023
d329c10
Reports worker exceptions
nunomaduro Dec 15, 2023
9a532d6
Displays anything different from 200
nunomaduro Dec 15, 2023
904d037
Shutdowns on server exception boot
nunomaduro Dec 15, 2023
515a6f9
Fixes 500 responses from worker
nunomaduro Dec 15, 2023
484e470
Don't publish caddyfile
nunomaduro Dec 15, 2023
c47de88
Fixes double realpath call
nunomaduro Dec 15, 2023
73e401b
Fixes method name
nunomaduro Dec 15, 2023
f4a5ddf
Dont ignore caddy
nunomaduro Dec 15, 2023
1e99c9c
Fix logs in non local
nunomaduro Dec 15, 2023
d2a7fed
warn
nunomaduro Dec 15, 2023
2410ba3
dont report to master
nunomaduro Dec 15, 2023
48e64e1
Fixes method "put" not getting caught
nunomaduro Dec 18, 2023
af4ae4d
Uses mercure `demo` when requested
nunomaduro Dec 18, 2023
bfc8306
Don't display mercure stuff
nunomaduro Dec 18, 2023
b21b6b8
Adds link to readme:
nunomaduro Dec 18, 2023
cddc22a
Update README.md
taylorotwell Dec 18, 2023
3781b16
Update InstallsFrankenPhpDependencies.php
taylorotwell Dec 18, 2023
2dd3c21
Update InstallCommand.php
taylorotwell Dec 18, 2023
5e754ed
Update StartCommand.php
taylorotwell Dec 18, 2023
6a45c36
Update StartFrankenPhpCommand.php
taylorotwell Dec 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ trim_trailing_whitespace = false

[*.{yml,yaml}]
indent_size = 2

[Caddyfile]
indent_style = tab
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

- Fix passing invalid connection session id to `Swoole\Http\Response::create()` by [@smortexa](https://github.com/smortexa) in https://github.com/laravel/octane/pull/737
- Fix missing mode config by [@sy-records](https://github.com/sy-records) in https://github.com/laravel/octane/pull/740
- Add raw type in handleStream method for custom json in stdout by [@mphamid](https://github.com/mphamid) in https://github.com/laravel/octane/pull/742
- Add `raw` type in handleStream method for custom json in stdout by [@mphamid](https://github.com/mphamid) in https://github.com/laravel/octane/pull/742

## [v2.0.5](https://github.com/laravel/octane/compare/v2.0.4...v2.0.5) - 2023-08-08

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

## Introduction

Laravel Octane supercharges your application's performance by serving your application using high-powered application servers, including [Open Swoole](https://openswoole.com), [Swoole](https://github.com/swoole/swoole-src), and [RoadRunner](https://roadrunner.dev). Octane boots your application once, keeps it in memory, and then feeds it requests at supersonic speeds.
Laravel Octane supercharges your application's performance by serving your application using high-powered application servers, including [Open Swoole](https://openswoole.com), [Swoole](https://github.com/swoole/swoole-src), [RoadRunner](https://roadrunner.dev), and [FrankenPHP](https://frankenphp.dev). Octane boots your application once, keeps it in memory, and then feeds it requests at supersonic speeds.

## Official Documentation

Expand Down
5 changes: 3 additions & 2 deletions bin/bootstrap.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use Laravel\Octane\Exceptions\DdException;
use Laravel\Octane\Octane;

ini_set('display_errors', 'stderr');

Expand All @@ -20,7 +21,7 @@
$basePath = $_SERVER['APP_BASE_PATH'] ?? $_ENV['APP_BASE_PATH'] ?? $serverState['octaneConfig']['base_path'] ?? null;

if (! is_string($basePath)) {
fwrite(STDERR, 'Cannot find application base path.'.PHP_EOL);
Octane::writeError('Cannot find application base path.');

exit(11);
}
Expand All @@ -45,7 +46,7 @@ function dd(...$vars)
*/

if (! is_file($autoload_file = $basePath.'/vendor/autoload.php')) {
fwrite(STDERR, "Composer autoload file was not found. Did you install the project's dependencies?".PHP_EOL);
Octane::writeError("Composer autoload file was not found. Did you install the project's dependencies?");

exit(10);
}
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "laravel/octane",
"description": "Supercharge your Laravel application's performance.",
"keywords": ["laravel", "octane", "roadrunner", "swoole"],
"keywords": ["laravel", "octane", "roadrunner", "swoole", "frankenphp"],
"license": "MIT",
"support": {
"issues": "https://github.com/laravel/octane/issues",
Expand Down
42 changes: 31 additions & 11 deletions config/octane.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
| when starting, restarting, or stopping your server via the CLI. You
| are free to change this to the supported server of your choosing.
|
| Supported: "roadrunner", "swoole"
| Supported: "roadrunner", "swoole", "frankenphp"
|
*/

Expand Down Expand Up @@ -137,7 +137,25 @@

/*
|--------------------------------------------------------------------------
| Octane Cache Table
| Octane Swoole Tables
|--------------------------------------------------------------------------
|
| While using Swoole, you may define additional tables as required by the
| application. These tables can be used to store data that needs to be
| quickly accessed by other workers on the particular Swoole server.
|
*/

'tables' => [
'example:1000' => [
'name' => 'string:1000',
'votes' => 'int',
],
],

/*
|--------------------------------------------------------------------------
| Octane Swoole Cache Table
|--------------------------------------------------------------------------
|
| While using Swoole, you may leverage the Octane cache, which is powered
Expand All @@ -153,20 +171,22 @@

/*
|--------------------------------------------------------------------------
| Octane Swoole Tables
| FrankenPHP Mercure Hub
|--------------------------------------------------------------------------
|
| While using Swoole, you may define additional tables as required by the
| application. These tables can be used to store data that needs to be
| quickly accessed by other workers on the particular Swoole server.
| This option configures the Mercure hub (event broadcasting) that ships
| with FrankenPHP. The defaults provided here should be sufficient on
| most applications. However, you are free to tweak them as needed.
|
| See: https://mercure.rocks
|
*/

'tables' => [
'example:1000' => [
'name' => 'string:1000',
'votes' => 'int',
],
'mercure' => [
'publisher_jwt' => env('MERCURE_PUBLISHER_JWT_KEY', 'your-publisher-key'),
'subscriber_jwt' => env('MERCURE_SUBSCRIBER_JWT_KEY', 'your-subscriber-key'),
'anonymous' => true, // Enable anonymous subscriptions...
'subscriptions' => true, // Enable subscription API
],

/*
Expand Down
104 changes: 104 additions & 0 deletions src/Commands/Concerns/InstallsFrankenPhpDependencies.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

namespace Laravel\Octane\Commands\Concerns;

use GuzzleHttp\Client;
use Illuminate\Support\Facades\Http;
use Laravel\Octane\FrankenPhp\Concerns\FindsFrankenPhpBinary;

trait InstallsFrankenPhpDependencies
{
use FindsFrankenPhpBinary;

/**
* Ensure the FrankenPHP binary is installed into the project.
*/
protected function ensureFrankenPhpBinaryIsInstalled(): string
{
if (! is_null($frankenphpBinary = $this->findFrankenPhpBinary())) {
return $frankenphpBinary;
}

if ($this->confirm('Unable to locate FrankenPHP binary. Should Octane download the binary for your operating system?', true)) {
$this->downloadFrankenPhpBinary();

copy(__DIR__.'/../stubs/Caddyfile', base_path('Caddyfile'));
copy(__DIR__.'/../stubs/frankenphp-worker.php', public_path('frankenphp-worker.php'));
}

return base_path('frankenphp');
}

/**
* Download the latest version of the FrankenPHP binary.
*
* @return bool
*/
protected function downloadFrankenPhpBinary()
{
$arch = php_uname('m');

$assetName = match (true) {
PHP_OS_FAMILY === 'Linux' && $arch === 'x86_64' => 'frankenphp-linux-x86_64',
PHP_OS_FAMILY === 'Darwin' => "frankenphp-mac-$arch",
default => null,
};

if ($assetName === null) {
$this->error('FrankenPHP binaries are currently only available for Linux (x86_64) and macOS. Other systems should use the Docker images or compile FrankenPHP manually.');

return false;
}

$assets = Http::accept('application/vnd.github+json')
->withHeaders(['X-GitHub-Api-Version' => '2022-11-28'])
->get('https://api.github.com/repos/dunglas/frankenphp/releases/latest')['assets'];

foreach ($assets as $asset) {
if ($asset['name'] !== $assetName) {
continue;
}

$path = base_path('frankenphp');

$progressBar = null;

(new Client)->get(
$asset['browser_download_url'],
[
'sink' => $path,
'progress' => function ($downloadTotal, $downloadedBytes) use (&$progressBar) {
if ($downloadTotal === 0) {
return;
}

if ($progressBar === null) {
$progressBar = $this->output->createProgressBar($downloadTotal);
$progressBar->start($downloadTotal, $downloadedBytes);

return;
}

$progressBar->setProgress($downloadedBytes);
},
]
);

chmod($path, 0755);

$progressBar->finish();

$this->newLine();

if (PHP_OS_FAMILY === 'Darwin') {
$this->warn("You may need to run `xattr -d com.apple.quarantine $path` to release FrankenPHP from Apple's quarantine before starting the server.");
}

return $path;
}

$this->error('FrankenPHP asset not found.');

return $path;
}
}
3 changes: 2 additions & 1 deletion src/Commands/Concerns/InteractsWithIO.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Laravel\Octane\Exceptions\DdException;
use Laravel\Octane\Exceptions\ServerShutdownException;
use Laravel\Octane\Exceptions\WorkerException;
use Laravel\Octane\Octane;
use Laravel\Octane\WorkerExceptionInspector;
use NunoMaduro\Collision\Writer;
use Symfony\Component\VarDumper\VarDumper;
Expand Down Expand Up @@ -46,7 +47,7 @@ public function raw($string)
{
if (! Str::startsWith($string, $this->ignoreMessages)) {
$this->output instanceof OutputStyle
? fwrite(STDERR, $string."\n")
? Octane::writeError($string)
: $this->output->writeln($string);
}
}
Expand Down
10 changes: 7 additions & 3 deletions src/Commands/Concerns/InteractsWithServers.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ protected function writeServerRunningMessage()

$this->output->writeln([
'',
' Local: <fg=white;options=bold>http://'.$this->getHost().':'.$this->getPort().' </>',
' Local: <fg=white;options=bold>'.($this->hasOption('https') && $this->option('https') ? 'https://' : 'http://').$this->getHost().':'.$this->getPort().' </>',
'',
' <fg=yellow>Press Ctrl+C to stop the server</>',
'',
Expand All @@ -114,10 +114,14 @@ protected function writeServerRunningMessage()
*/
protected function getServerOutput($server)
{
return tap([
$output = [
$server->getIncrementalOutput(),
$server->getIncrementalErrorOutput(),
], fn () => $server->clearOutput()->clearErrorOutput());
];

$server->clearOutput()->clearErrorOutput();

return $output;
}

/**
Expand Down
30 changes: 28 additions & 2 deletions src/Commands/InstallCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

class InstallCommand extends Command
{
use Concerns\InstallsRoadRunnerDependencies;
use Concerns\InstallsFrankenPhpDependencies,
Concerns\InstallsRoadRunnerDependencies;

/**
* The command's signature.
Expand All @@ -34,12 +35,13 @@ public function handle()
{
$server = $this->option('server') ?: $this->choice(
'Which application server you would like to use?',
['roadrunner', 'swoole'],
['roadrunner', 'swoole', 'frankenphp'],
);

return (int) ! tap(match ($server) {
'swoole' => $this->installSwooleServer(),
'roadrunner' => $this->installRoadRunnerServer(),
'frankenphp' => $this->installFrankenPhpServer(),
default => $this->invalidServer($server),
}, function ($installed) use ($server) {
if ($installed) {
Expand Down Expand Up @@ -116,6 +118,30 @@ public function installSwooleServer()
return true;
}

/**
* Install the FrankenPHP server.
*
* @return bool
*/
public function installFrankenPhpServer()
{
$gitIgnorePath = base_path('.gitignore');

if (File::exists($gitIgnorePath)) {
$contents = File::get($gitIgnorePath);

$filesToAppend = collect(['frankenphp', 'Caddyfile', 'frankenphp-worker.php'])
->filter(fn ($file) => ! str_contains($contents, $file.PHP_EOL))
->implode(PHP_EOL);

if ($filesToAppend !== '') {
File::append($gitIgnorePath, PHP_EOL.$filesToAppend.PHP_EOL);
}
}

return $this->ensureFrankenPhpBinaryIsInstalled();
}

/**
* Inform the user that the server type is invalid.
*
Expand Down
24 changes: 24 additions & 0 deletions src/Commands/ReloadCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Laravel\Octane\Commands;

use Laravel\Octane\FrankenPhp\ServerProcessInspector as FrankenPhpServerProcessInspector;
use Laravel\Octane\RoadRunner\ServerProcessInspector as RoadRunnerServerProcessInspector;
use Laravel\Octane\Swoole\ServerProcessInspector as SwooleServerProcessInspector;

Expand Down Expand Up @@ -33,6 +34,7 @@ public function handle()
return match ($server) {
'swoole' => $this->reloadSwooleServer(),
'roadrunner' => $this->reloadRoadRunnerServer(),
'frankenphp' => $this->reloadFrankenPhpServer(),
default => $this->invalidServer($server),
};
}
Expand Down Expand Up @@ -81,6 +83,28 @@ protected function reloadRoadRunnerServer()
return 0;
}

/**
* Reload the FrankenPHP server for Octane.
*
* @return int
*/
protected function reloadFrankenPhpServer()
{
$inspector = app(FrankenPhpServerProcessInspector::class);

if (! $inspector->serverIsRunning()) {
$this->error('Octane server is not running.');

return 1;
}

$this->info('Reloading workers...');

$inspector->reloadServer();

return 0;
}

/**
* Inform the user that the server type is invalid.
*
Expand Down
Loading