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

RoadRunner v2 support #31

Merged
merged 18 commits into from
Apr 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
fail-fast: false
matrix:
operating-system: [ubuntu-latest]
php-versions: ['7.3', '7.4', '8.0']
php-versions: ['7.4', '8.0']
composer:
- {name: "lowest", flags: " --prefer-dist --prefer-lowest"}
- {name: "stable", flags: " --prefer-dist --prefer-stable"}
Expand Down
1 change: 1 addition & 0 deletions .php_cs.dist
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ return PhpCsFixer\Config::create()
'include' => ['@compiler_optimized']
],
'php_unit_method_casing' => false,
'declare_strict_types' => true
])
;
25 changes: 22 additions & 3 deletions .rr.dev.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
include:
- .rr.yaml
server:
command: "php bin/console baldinof:roadrunner:worker"

http:
address: 0.0.0.0:8080
middleware: [ "static", "gzip" ]
uploads:
forbid: [ ".php", ".exe", ".bat" ]
static:
dir: "public"
forbid: [ ".php", ".htaccess" ]

logs:
mode: development
channels:
http:
level: debug # Log all http requests, set to info to disable
server:
level: debug # Everything written to worker stderr is logged
metrics:
level: debug

reload:
enabled: true
interval: 1s
patterns: [".php"]
patterns: [".php", ".yaml"]
services:
http:
dirs: ["."]
Expand Down
35 changes: 26 additions & 9 deletions .rr.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
http:
address: "0.0.0.0:8080"
server:
command: "php bin/console baldinof:roadrunner:worker"

http:
address: 0.0.0.0:8080
middleware: [ "static", "gzip" ]
uploads:
forbid: [".php", ".exe", ".bat"]
forbid: [ ".php", ".exe", ".bat" ]
static:
dir: "public"
forbid: [ ".php", ".htaccess" ]

logs:
mode: production
channels:
http:
level: debug # Log all http requests, set to info to disable
server:
level: debug # Everything written to worker stderr is logged
metrics:
level: error

workers:
command: "php bin/console baldinof:roadrunner:worker"
relay: "unix://var/roadrunner.sock"
# Uncomment to use metrics integration
# rpc:
# listen: tcp://127.0.0.1:6001

static:
dir: "public"
forbid: [".php", ".htaccess"]
# Uncomment to use metrics integration
# metrics:
# # prometheus client address (path /metrics added automatically)
# address: "0.0.0.0:9180"
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.0.0-beta]

### Added
- Support for RoadRunner 2.x
- Metrics declaration via Symfony configuration
- Automatic detection of relay address (thanks to RR v2)

### Changed
- Moved all integration code to the `Integration` namespace
- No more PSR / Symfony conversion, the internal worker uses Symfony requests and responses directly

### Removed
- PSR Middleware supports

## [1.5.3] - 2021-03-30

### Fixed
Expand Down
140 changes: 50 additions & 90 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,65 +22,26 @@ If you don't use Symfony Flex:
- run RoadRunner with `bin/rr serve`
- visit your app at http://localhost:8080

## Configuration

If you want to override some parts of the bundle you can replace some definitions.

Example if you want to use a TCP socket as relay:

```yaml
# config/services.yaml
services:
Spiral\Goridge\RelayInterface:
class: 'Spiral\Goridge\SocketRelay'
arguments:
- localhost
- 7000
```

```yaml
# .rr.yaml
http:
workers:
relay: "tcp://localhost:7000"
```

## Integrations

Depending on installed bundle & your configuration, this bundles add some integrations:

- Sentry: configure the request context (if the [`SentryBundle`](https://github.com/getsentry/sentry-symfony) is installed)
- Sessions: add the session cookie to the PSR response (if `framework.sessions.enabled` config is `true`)
- Doctrine Mongo Bundle: call `clear()` on all opened manager after each requests (not needed for regular doctrine bundle)
- **Sentry**: configure the request context (if the [`SentryBundle`](https://github.com/getsentry/sentry-symfony) is installed)
- **Sessions**: add the session cookie to the Symfony response (if `framework.sessions.enabled` config is `true`)
- **Doctrine Mongo Bundle**: clear opened managers after each requests (if [`DoctrineMongoDBBundle`](https://github.com/doctrine/DoctrineMongoDBBundle) is installed)
- **Doctrine ORM Bundle**: clear opened managers and check connection is still usable after each requests (if [`DoctrineBundle`](https://github.com/doctrine/DoctrineBundle) is installed)
- **Blackfire**: enable the probe when a profile is requested (if the [`blackfire`](https://blackfire.io/) extension is installed)

Default integrations can be disabled:
Even if it is not recommended, you can disable default integrations:

```yaml
baldinof_road_runner:
default_integrations: false
```

## Doctrine connection handler
Due to the fact that roadrunner assumes that the process works in demonized mode, there may be problems with disconnecting the database, this problem is handled in this bundle if a doctrine is used to connect to the database.

By default, in the event of a connection failure, the process will be stopped and the request will end with a 500 http code, to prevent this and to correctly process failed connections, without erroneous answers - you need to add [symfony/proxy-manager-bridge](https://github.com/symfony/proxy-manager-bridge) to your project:
```
composer require symfony/proxy-manager-bridge
```

## Sessions in database
In accordance with the problem described above, to store sessions in the database, you should use the doctrine connection, for example, you can use the [shapecode/doctrine-session-handler-bundle](https://github.com/shapecode/doctrine-session-handler-bundle) bundle

```
composer require shapecode/doctrine-session-handler-bundle
```

## Middlewares

You can use middlewares to manipulate PSR request & responses. Middlewares can implements either PSR [`MiddlewareInterface`](https://www.php-fig.org/psr/psr-15/#22-psrhttpservermiddlewareinterface)
or [`Baldinof\RoadRunnerBundle\Http\IteratorMiddlewareInterface`](./src/Http/IteratorMiddlewareInterface.php).

`IteratorMiddlewareInterface` allows to do work after the response has been sent to the client, you just have to `yield` the response instead of returning it.
You can use middlewares to manipulate request & responses. Middlewares must implements [`Baldinof\RoadRunnerBundle\Http\MiddlewareInterface`](./src/Http/MiddlewareInterface.php).

Example configuration:

Expand All @@ -94,52 +55,11 @@ Be aware that
- middlewares are run outside of Symfony `Kernel::handle()`
- the middleware stack is always resolved at worker start (can be a performance issue if your middleware initialization takes time)

## Metrics
Roadrunner have ability to [collect application metrics](https://roadrunner.dev/docs/beep-beep-metrics), enable metrics with this bundle configuration:

```yaml
# config/packages/baldinof_road_runner.yaml
baldinof_road_runner:
metrics_enabled: true
```

And configure RoadRunner:

```yaml
# .rr.yaml
rpc:
enable: true
listen: unix://var/roadrunner_rpc.sock

metrics:
address: localhost:2112
collect:
app_metric_counter:
type: counter
help: "Application counter."
```

Simply inject `Spiral\RoadRunner\MetricsInterface` to record metrics:

```php
class YouController
{
public function index(MetricsInterface $metrics): Response
{
$metrics->add('app_metric_counter', 1);

return new Response("...");
}
}
```

> If you inject `Spiral\RoadRunner\MetricsInterface`, but metrics collection is disabled in config, a [`NullMetrics`](./src/Metric/NullMetrics.php) will be injected and nothing will be collected.

## Kernel reboots

The Symfony kernel and the dependency injection container are **preserved between requests**. If an exception is thrown during the request handling, the kernel is rebooted and a fresh container is used.

The goal is to prevent services to be in a non recoverable state after an error.
The goal is to prevent services to be in a non-recoverable state after an error.

To optimize your worker you can allow exceptions that does not put your app in an errored state:

Expand All @@ -153,6 +73,7 @@ baldinof_road_runner:
- Symfony\Component\Serializer\Exception\ExceptionInterface
- App\Exception\YourDomainException
```
> If some of your services are stateful, you can implement `Symfony\Contracts\Service\ResetInterface` and your service will be resetted on each request.

If you are seeing issues and want to use a fresh container on each request you can use the `always` reboot strategy:

Expand All @@ -163,8 +84,6 @@ baldinof_road_runner:
strategy: always
```

> If some of your services are stateful, you can implement `Symfony\Contracts\Service\ResetInterface` and your service will be resetted on each request.

## Events

The following events are dispatched throughout the worker lifecycle:
Expand All @@ -188,6 +107,47 @@ Reference: https://roadrunner.dev/docs/beep-beep-reload

If you use the Symfony VarDumper, dumps will not be shown in the HTTP Response body. You can view dumps with `bin/console server:dump` or in the profiler.

## Metrics
Roadrunner can [collect application metrics](https://roadrunner.dev/docs/beep-beep-metrics), and expose a prometheus endpoint.

Example configuration:

```yaml
# config/packages/baldinof_road_runner.yaml
baldinof_road_runner:
metrics:
enabled: true
collect:
user_login:
type: counter
help: "Number of logged in user"
```

And configure RoadRunner:

```yaml
# .rr.yaml
rpc:
listen: "tcp:127.0.0.1:6001"

metrics:
address: "0.0.0.0:9180" # prometheus endpoint
```

Then simply inject `Spiral\RoadRunner\MetricsInterface` to record metrics:

```php
class YouController
{
public function index(MetricsInterface $metrics): Response
{
$metrics->add('user_login', 1);

return new Response("...");
}
}
```

## Usage with Docker

```Dockerfile
Expand Down
37 changes: 37 additions & 0 deletions UPGRAGE-2-0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Upgrading from RoadRunner Bundle 1.x to 2.x

Version 2.0 has a lot of breaking changes as it _totally removed the PSR layer_, and _many classes as been moved_,
however it's mainly internals changes, if you don't use custom middleware **you should be good by just migrating to the new
configuration format**:

```yaml
baldinof_road_runner:
# When the kernel should be rebooted.
# See https://github.com/baldinof/roadrunner-bundle#kernel-reboots
kernel_reboot:
# if you want to use a fresh container on each request, use the `always` strategy
strategy: on_exception
# Exceptions you KNOW that do not put your app in an errored state
allowed_exceptions:
- Symfony\Component\HttpKernel\Exception\HttpExceptionInterface
- Symfony\Component\Serializer\Exception\ExceptionInterface
- Symfony\Contracts\HttpClient\Exception\ExceptionInterface

# Allow to send prometheus metrics to the main RoadRunner process,
# via a `Spiral\RoadRunner\MetricsInterface` service.
# See https://github.com/baldinof/roadrunner-bundle#metrics
metrics:
enabled: false
# collect:
# my_counter:
# type: counter
# help: Some help


# You can use middlewares to manipulate Symfony requests & responses.
# See https://github.com/baldinof/roadrunner-bundle#middlewares
# middlewares:
# - App\Middleware\YourMiddleware
```

If you have custom PSR middlewares, you should migrate to the new [`MiddlewareInterface`](./src/Http/MiddlewareInterface.php) that directly use Symfony HttpFoundation instead of PSR classes.
28 changes: 13 additions & 15 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,16 @@
}
},
"require": {
"php": ">=7.3",
"php": ">=7.4",
"symfony/config": "^4.4 || ^5.0",
"symfony/dependency-injection": "^4.4 || ^5.0",
"symfony/http-kernel": "^4.4 || ^5.0",
"symfony/yaml": "^4.4 || ^5.0",
"spiral/roadrunner": "^1.5",
"spiral/goridge": "^2.0.2",
"spiral/roadrunner": "^2.0.2",
"spiral/roadrunner-worker": ">=2.0.3",
"spiral/goridge": "^3.0",
"symfony/psr-http-message-bridge": "^1.1 || ^2.0",
"psr/http-factory": "^1.0",
"psr/http-server-handler": "^1.0",
"psr/http-server-middleware": "^1.0",
"dflydev/fig-cookies": "^3.0",
"php-http/discovery": "^1.9",
"psr/http-factory-implementation": "1.0.0",
"psr/log": "^1.1",
"jean85/pretty-package-versions": "^1.5 || ^2.0"
"psr/log": "^1.1"
},
"suggest": {
"nyholm/psr7": "For a super lightweight PSR-7/17 implementation",
Expand All @@ -44,19 +38,23 @@
"phpspec/prophecy": "^1.11",
"phpspec/prophecy-phpunit": "^2.0",
"friendsofphp/php-cs-fixer": "^2.16",
"phpstan/phpstan": "^0.12.2",
"sentry/sentry-symfony": "^3.4||^4.0",
"phpstan/phpstan": "0.12.80",
"sentry/sentry-symfony": "^4.0",
"symfony/framework-bundle": "^4.0||^5.0",
"nyholm/psr7": "^1.2",
"doctrine/mongodb-odm": "^2.2",
"blackfire/php-sdk": "^1.21",
"doctrine/doctrine-bundle": "^2.1.1",
"doctrine/orm": "^2.7.3",
"symfony/proxy-manager-bridge": "^4.0 || ^5.0",
"ocramius/package-versions": "^1.10 || ^2.0"
"spiral/roadrunner-metrics": "^2.0.1",
"mikey179/vfsstream": "^1.6.8",
"pestphp/pest-plugin-expectations": "^1.0"
},
"conflict": {
"doctrine/doctrine-bundle": "<2.1.1"
"doctrine/doctrine-bundle": "<2.1.1",
"sentry/sentry-symfony": "<4.0.0",
"spiral/roadrunner-metrics": "<2.0.1"
},
"scripts": {
"test": "phpunit --testdox --colors=always",
Expand Down
Loading