Download the PHP package fluffydiscord/roadrunner-symfony-bundle without Composer

On this page you can find all versions of the php package fluffydiscord/roadrunner-symfony-bundle. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package roadrunner-symfony-bundle

RoadRunner Runtime for Symfony

Yet another runtime for Symfony and RoadRunner.

DDEV users: see DDEV add-on.

Features

Installation

Usage

  1. .rr.yaml:

.env — RR_RPC must match rpc.listen:

  1. Swap the kernel trait:

Service reset

New request arrives Your app After the response is sent
Stock Symfony resets services first (on the request path) handled after reset nothing
This bundle container already warm handled immediately terminate(), then services_resetter reset

Non-shared services (shared: false) are not reset before Symfony 8.1, even with ResetInterface — services_resetter resets a throwaway instance. Fixed in 8.1.

Database connections

The ORM identity map is cleared for you (doctrine registry implements ResetInterface). The above concerns the DBAL connection.

Configuration

fluffy_discord_road_runner.yaml

Option Default Meaning
rr_config_path .rr.yaml Path to RR config, relative to kernel.project_dir. Lets cache:warmup run without RR running (Docker builds).
*.lazy_boot false false = boot kernel before first request (slower worker ready, consistent response times). true = boot on first request (instant ready, boot-time spikes). Many workers → true, or boot a few workers + dynamic scaling.
http.request_factory auto native = build the Symfony Request directly, ~halves conversion cost. psr7 = PSR-7 then symfony/psr-http-message-bridge; use with a custom HttpFoundationFactoryInterface service (picked up automatically). auto = psr7 when such a service exists, else native.
warmup.enabled true Master switch for the warmup runner, built-in warmers and the recorder. See Worker warmup.
warmup.learn true Record which classes and cache files real responses load, replay them at every later worker boot. Covers only routes visited while learning.
warmup.learn_requests 30 Stop recording after this many responses per worker process.
warmup.manifest_path null null = <kernel.cache_dir>/roadrunner/warmup.manifest.json. Point outside the cache dir to persist learning across deploys; self-invalidates when the container build id changes.
doctrine.preconnect true Opens PostgreSQL connections at worker boot; other drivers ignored; runs on every boot regardless of lazy_boot. Needs doctrine/dbal.
kv.auto_register true Registers every kv adapter from .rr.yaml as cache.adapter.rr_kv.NAME.
kv.serializer null IgbinarySerializer when the igbinary extension is present, else DefaultSerializer. Custom: implement Spiral\RoadRunner\KeyValue\Serializer\SerializerInterface.
kv.keypair_path — Relative path to a keypair for end-to-end encryption. Needs sodium.

Each section activates only with its package installed:

Section Package
centrifugo roadrunner-php/centrifugo
jobs spiral/roadrunner-jobs
kv spiral/roadrunner-kv
doctrine doctrine/dbal
temporal temporal/sdk — options in docs/temporal.md

Behind a load balancer / reverse proxy

Use private_ranges instead of REMOTE_ADDR as trusted proxy. The REMOTE_ADDR placeholder is resolved from $_SERVER at container build time, where no request exists yet, so trusted headers won't work. The per-request client IP is on the Request ($request->server->get('REMOTE_ADDR')), never in $_SERVER.

Response/file streaming

BinaryFileResponse, StreamedResponse, StreamedJsonResponse are fully supported. Although streamed callbacks must return a \Generator — replace echo with yield:

Early Hints (103)

sendEarlyHints() works out of the box via a headers_send() polyfill. See Symfony docs.

Error handling

Failure dev (kernel.debug) prod
exception in your code Symfony's exception page Symfony's error page
exception escaping Symfony HtmlErrorRenderer page bare 500, empty body
die() / exit() / fatal built-in minimal error page bare 500, empty body

Not covered:

Best dev experience: socket relay (RR_RELAY=tcp://…/unix://…) or http.pool.debug: true.

Sentry

Configure as usual.

Monolog

Avoid the fingers_crossed handler — it leaks memory by design. It still mostly works here because ServiceResetter runs after each response, but logs may be missing after a hard error.

Centrifugo (websockets)

Listen to any event implementing FluffyDiscord\RoadRunnerBundle\Event\Centrifugo\CentrifugoEventInterface:

Nobody answered → denied (since v8, see UPGRADE). Every request needs a listener that calls setResponse(), reject() or disconnect():

Request Default when unanswered
Connect disconnect 4500 forbidden (client does not reconnect)
Publish, Subscribe, RPC error 403 forbidden
Refresh, SubRefresh result expired: true (client disconnected)

Refusing a request

ConnectEvent, PublishEvent, SubscribeEvent and RPCEvent refuse without throwing. Both stop propagation; no later listener runs.

#[AsCentrifugoChannelListener]

Routes PublishEvent, SubscribeEvent, SubRefreshEvent, ConnectEvent by channel name. * = wildcard.

On a class, event and method are required:

Parameter Type Default Description
channel string (required) Exact name or * pattern (chat:*)
event ?string null Event FQCN; inferred from the first parameter type hint on methods
priority int 0 Higher = called first within the matched channel
method ?string null Auto-detected when placed on a method

#[AsCentrifugoRpcListener]

Routes RPCEvent by RPC method name.

Parameter Type Default Description
rpcMethod string (required) Matched against RPCEvent::getRequest()->method
priority int 0 Higher = called first
method ?string null Auto-detected when placed on a method

Routing table is built at container compile time — one hash-map lookup per request. Handlers run in priority order and respect stopPropagation(). Routing listeners fire at priority -100, after plain #[AsEventListener] handlers at 0.

Jobs (queues)

.rr.yaml:

JobsRunEvent is dispatched once per consumed task:

Ack / nack:

Poison messages: the default is requeue, so an always-throwing task is redelivered indefinitely. Catch inside the listener and ack-and-drop, or nack($e, redelivery: false) yourself.

Message bus (Messenger-style)

Optional typed layer: dispatch a plain PHP object, handle it with a standard #[AsMessageHandler]. Purely additive — raw JobsRunEvent and RR Jobs services keep working, and a task this layer did not produce is left to your raw listeners.

Serialization: igbinary when the extension is present, otherwise Native (serialize()/unserialize(), handles any serializable object incl. private state). For JSON:

The strategy comes from jobs.serializer (igbinary / native / symfony) and is recorded in the task's x-job-serializer header so the consumer decodes with the same one. symfony without symfony/serializer throws a clear error.

Dispatch via the public JobDispatcher; explicit arguments override the attribute:

Everything #[AsMessageHandler] supports applies — priorities, multiple handlers, named methods, debug:messenger. Consumed jobs arrive on the Messenger transport roadrunner; scope with #[AsMessageHandler(fromTransport: 'roadrunner')].

Need the RR task (headers, manual ack/nack/requeue)? Add a ReceivedTaskInterface parameter:

Ack / nack matches the raw listener: all handlers return → ack; a handler throws → nack with requeue + STDERR / Sentry log; no registered handler → logged and acked as a no-op. The poison-message caveat applies equally.

Wire format (x-job-class / x-job-serializer headers, message FQCN as the RR job name) is a stable contract — changing it breaks in-flight queued tasks across an upgrade.

Worker warmup

A fresh worker's first request is several times slower than steady state; opcache.preload is a no-op in cli workers. The bundle warms during worker boot, before RR marks the worker ready. Zero config:

  1. Generic warmers — router, Doctrine metadata, event listeners, form types, Twig runtimes, container preload class list. Missing dependencies are skipped.
  2. Learned manifest — workers record what real traffic loads (<kernel.cache_dir>/roadrunner/warmup.manifest.json); every next worker replays it at boot. Invalidated when the container is rebuilt.

Measured on a production Sylius app: first request 252 ms → 41 ms (steady state 33–43 ms).

Development (http.pool.debug: true): warmup and learning switch themselves off — one process per request keeps nothing warm. Gate is kernel.runtime_mode.worker, derived from pool.debug in .rr.yaml.

Production expectations:

Warmed classes live in each worker's opcache — budget opcache.memory_consumption × worker count.

Warming your own services

Autoconfigured. Or listen to WorkerBootingEvent. A throwing warmer is logged and skipped in production.

Cold cache in dev

Suggested, not required. Sidesteps upstream Symfony bug: symfony/symfony#65447

Distributed locks

Optional. Symfony LockFactory backed by RR's Lock plugin over the same RPC, no extra config:

Add a lock section to .rr.yaml, then autowire LockFactory (or PersistingStoreInterface):

Temporal (beta)

[!WARNING] Beta. Flow and implementation may still change; expect breaking changes until the API settles.

Put workflows and activities on a task queue with #[TaskQueue], start them with WorkflowLauncherInterface.

→ docs/temporal.md

Developing with Symfony and RoadRunner

OptionsResolver (Forms)

OptionsResolver::setDefaults() is cached — it resolves once per worker, on first use. Dynamic defaults leak across requests and sessions:

Keep defaults static; pass dynamic values at form creation:

Debugging

DDEV add-on

See the add-on repository for configuration and usage.

Credits

Inspiration taken from Baldinof's Bundle and Nyholm's Runtime.


All versions of roadrunner-symfony-bundle with dependencies

PHP Build Version
Package Version
Requires php Version >=8.4
nyholm/psr7 Version ^1.8
spiral/roadrunner Version ^v2025 || ^3
symfony/dependency-injection Version ^7.4 || ^8
symfony/http-kernel Version ^7.4 || ^8
symfony/psr-http-message-bridge Version ^7.4 || ^8
symfony/runtime Version ^7.4 || ^8
symfony/framework-bundle Version ^7.4 || ^8
symfony/event-dispatcher Version ^7.4 || ^8
symfony/expression-language Version ^7.4 || ^8
spiral/roadrunner-worker Version ^v3
spiral/roadrunner-http Version ^v4
spiral/roadrunner-cli Version ^v2
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package fluffydiscord/roadrunner-symfony-bundle contains the following files

Loading the files please wait ...