[13.x] Fix the FrankenPHP Mercure hub in the CLI and broadcast Mercure events synchronously by default

Merged
DU
20d ago
+118-8

Follow-up to https://github.com/laravel/framework/pull/61474 and https://github.com/laravel/framework/pull/61587.

Fix: the FrankenPHP hub broke the CLI. When no url is configured, the Mercure driver publishes through FrankenPHP's built-in hub. Resolving the broadcaster threw when mercure_publish() doesn't exist, so with BROADCAST_CONNECTION=mercure, every Artisan command loading routes/channels.php crashed, including octane:start and a second run of install:broadcasting --mercure. The hub now resolves everywhere, and broadcasting outside FrankenPHP throws a BroadcastException explaining that a url is needed.

Feature: Mercure broadcasts synchronously by default. Publishing to a Mercure hub is fast: the hub dispatches updates to subscribers asynchronously. Queueing the broadcast only adds a queue worker to run, and with FrankenPHP's built-in hub a queue worker can't even publish in-process. Events targeting only Mercure connections are now broadcast immediately, like ShouldBroadcastNow. Events also targeting other connections are still queued.

The new async option (MERCURE_ASYNC) restores queueing. It requires a url since queue workers publish over HTTP; FrankenPHP's built-in hub works through its URL:

MERCURE_URL="${APP_URL}/.well-known/mercure"
MERCURE_ASYNC=true

Both modes were tested end to end with Laravel Echo, Laravel Octane, and FrankenPHP 1.13 (public, private, presence channels and whispers).