sconcur / laravel
Laravel integration for SConcur: concurrent HTTP worker and coroutine-scoped application
Requires
- php: ^8.4
- laminas/laminas-diactoros: ^3.0
- laravel/framework: ^12.0
- sconcur/sconcur: 0.18.1
- symfony/psr-http-message-bridge: ^7.0 | ^8.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.94
- guzzlehttp/guzzle: ^7.0
- orchestra/testbench: ^10.0
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-28 11:26:06 UTC
README
English | Русский
SConcur Laravel
Laravel integration for SConcur: a concurrent HTTP worker and a coroutine-scoped application.
AsyncApplication goes into bootstrap/app.php as a subclass of
Illuminate\Foundation\Application. Inside a worker, every fiber gets its own
request, auth, session, cookie, config overlay, current route, locale,
View::share and defer. Outside a coroutine nothing changes: one caller, one instance.
The sconcur_mysql connection gives the ORM non-blocking MySQL and per-coroutine
transactions. The PDO-backed mysql connection has a transaction limit of its own — see
Database.
The sconcur client puts Redis:: on SConcur's Redis feature, and the sconcur_redis
cache store puts Cache:: there — see Redis.
Why
SConcur runs every HTTP request in its own PHP Fiber, concurrently, in one process.
Octane's model — cloning $app and swapping the global container — is not fiber-safe
under that kind of concurrency. This package keeps request state in the coroutine
context instead, swapping no global state and cloning no application.
The coroutine-scoped model (AsyncApplication plus per-coroutine state) is taken from
yangusik/laravel-spawn, where it sits on PHP
TrueAsync, and adapted to standard PHP plus SConcur (Context::current() in place of the
TrueAsync context). The worker's PSR-7 bridge follows Laravel Octane's model.
Documentation
| Document | About |
|---|---|
| Installation | requirements, the extension, the config, bootstrap/app.php, the first run |
| Layout | what lies where in the repository |
| Configuration (ENV) | every environment variable and its default |
| HTTP responses | how a response reaches the server, streamed responses sent chunked, output buffers in coroutines |
| Database | the sconcur_mysql connection, per-coroutine transactions, and the PDO connection's limit |
| Redis | the sconcur Redis client, the sconcur_redis cache store, and what they refuse |
| Filesystem | the sconcur_local disk and the File facade on the Files feature |
| Queue | the sconcur_rabbitmq driver and the consumer pool |
| WebSocket | the ws pool: examples, the protocol, channel signatures, the bus, presence |
| The task pool | periodic tasks, a coroutine each |
| Development | the docker environment, make, the tests |
| The demo application | what the demo shows and how to run it |
Every document exists in English and in Russian; the switcher is on its first line.
The runtimes
Four of them, all groups of one supervisor process, the SConcur master
(sconcur:servers:master:start), configured as groups in config/sconcur.php.
| Runtime | Foreground command | Document |
|---|---|---|
| HTTP server | sconcur:servers:http:start |
Installation, HTTP responses |
| Queue consumers | sconcur:servers:rabbitmq:start |
Queue |
| WebSocket | sconcur:servers:ws:start |
WebSocket |
| Periodic tasks | sconcur:tasks:start |
The task pool |
Artisan commands
sconcur:servers:master:start builds the library's WorkerMaster straight out of
config('sconcur.master') in its own process, once the application has booted. Every
worker is a fork of that process: it starts with the application already in memory and
runs its group's role — the HTTP server, the queue consumer pool, the WebSocket server or
the task pool. stop and status reach a running master through MasterControl, by its
runtimeDir and name.
sconcur:servers:master:start|stop # the supervisor: builds the master, forks the workers
sconcur:servers:master:status [--group=NAME] # status: every pool or one
sconcur:servers:http:start # one HTTP server in the foreground (build + serve)
sconcur:servers:rabbitmq:start # the queue consumer pool in the foreground
sconcur:rabbitmq:declare # declare the queues the pool reads — mandatory
sconcur:servers:ws:start # one WebSocket server in the foreground
sconcur:tasks:start [--only=NAME] # the periodic task pool in the foreground
sconcur:tasks:stop [--task=NAME] # stop the pool or one of its tasks
sconcur:tasks:restart [--task=NAME] # rebuild every task or one
sconcur:extension:load # download the .so (runs the downloader)
sconcur:extension:status # extension status (in-process)
There is no reload: a master holds the application it loaded, so new code or a new config
is a new master — master:stop, and the process supervisor starts it again.
The *:start commands of the four runtimes run one of them in the foreground without a
master; the HTTP, queue and WebSocket ones take the flags of their group's server block
unless given their own. The
handler is coroutine-safe (per-fiber context) and requests inside one process are handled
concurrently; a multi-process production setup is master:start.
The demo application
The repository carries a demo — a minimal Laravel application served by the SConcur master itself. It exists so the package can be looked at in operation rather than only read about.
make setup
Then http://localhost:48081 (the port is changed through APP_PORT in .env). What the
page shows and what is worth trying by hand is in demo/README.md.
An application installing the package the ordinary way needs none of this: there the
provider is found by auto-discovery and the config is published with
vendor:publish --tag=sconcur-laravel.