docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api
en/docs/api/json-rpc-bundle/functionality/events/README.md
new file +87
ā0
1
+
# Lifecycle events
2
+
3
+
Processing of every RPC request goes through [Symfony EventDispatcher](https://symfony.com/doc/current/event_dispatcher.html) events. By subscribing to them, you can add auditing, metrics and tracing, change method arguments or replace an error ā without changing the procedures.
4
+
5
+
:::warning
6
+
Listeners interfere with the server's work. Before changing data or stopping event propagation, read the page of the corresponding event: each one describes what is safe to change and what is not.
7
+
:::
8
+
9
+
## Event order
10
+
11
+
For a regular request with an `id`:
12
+
13
+
```
14
+
rpc.request
15
+
āā (cache: if #[RPC\Cache] has a response ā nothing else is dispatched)
16
+
rpc.pre_execute ā validation, parameter conversion, #[RPC\Lock], method call
17
+
āā success: rpc.pre_response ā rpc.post_execute
18
+
āā error: rpc.error ā rpc.pre_response
19
+
āā response sent to the client āā
20
+
rpc.post_response ā CacheRelation, notifications, $rpc.callback
21
+
```
22
+
23
+
For [notifications](/docs/api/json-rpc-bundle/functionality/notifications) and [`$rpc.callback`](/docs/api/json-rpc-bundle/functionality/callback), only `rpc.request` and `rpc.pre_response` with a placeholder response are dispatched on receipt, and the method itself runs in `rpc.post_response` ā with its own `rpc.pre_execute`, `rpc.pre_response`, `rpc.post_execute`. Full description ā on the [Lifecycle](/docs/api/json-rpc-bundle/developers/lifecycle) page.
24
+
25
+
## Event list
26
+
27
+
Names are constants of `Ufo\JsonRpcBundle\EventDrivenModel\Events\RpcEvent`, classes are in the same namespace.
28
+
29
+
| Event | Class | When |
30
+
| --- | --- | --- |
31
+
| [`rpc.request`](/docs/api/json-rpc-bundle/functionality/events/request) | `RpcRequestEvent` | Request received, before the cache check |
32
+
| [`rpc.pre_execute`](/docs/api/json-rpc-bundle/functionality/events/pre_execute) | `RpcPreExecuteEvent` | Before the method call; the method itself also runs here |
33
+
| [`rpc.post_execute`](/docs/api/json-rpc-bundle/functionality/events/post_execute) | `RpcPostExecuteEvent` | Method executed successfully |
34
+
| [`rpc.pre_response`](/docs/api/json-rpc-bundle/functionality/events/pre_response) | `RpcPreResponseEvent` | Response built |
35
+
| [`rpc.post_response`](/docs/api/json-rpc-bundle/functionality/events/post_response) | `RpcPostResponseEvent` | Response sent to the client |
36
+
| [`rpc.error`](/docs/api/json-rpc-bundle/functionality/events/error) | `RpcErrorEvent` | Error during execution |
37
+
| [`rpc.async_output`](/docs/api/json-rpc-bundle/functionality/events/async_output) | `RpcAsyncOutputEvent` | A batch child process returned a result |
38
+
| [`rpc.async_request`](/docs/api/json-rpc-bundle/functionality/events/async_request) | `RpcAsyncRequestEvent` | Declared, but the bundle does not dispatch it |
39
+
40
+
## Subscribing
41
+
42
+
```php
43
+
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
44
+
use Ufo\JsonRpcBundle\EventDrivenModel\Events\RpcEvent;
45
+
use Ufo\JsonRpcBundle\EventDrivenModel\Events\RpcPostResponseEvent;
46
+
47
+
#[AsEventListener(RpcEvent::POST_RESPONSE)]
48
+
final class AuditListener
49
+
{
50
+
public function __invoke(RpcPostResponseEvent $event): void
51
+
{
52
+
// $event->rpcRequest->getMethod(), $event->response ...
53
+
}
54
+
}
55
+
```
56
+
57
+
The priority is set in the attribute: `#[AsEventListener(RpcEvent::PRE_EXECUTE, priority: 500)]`. Higher priority runs earlier. The priorities of built-in listeners are listed on each event's page: they determine what your listener sees and whether it is called at all.
58
+
59
+
## General rules
60
+
61
+
* **Event properties are public and not readonly**, but assigning a new value does not always take effect ā see the event's page.
62
+
* **`stopPropagation()`** stops not only your neighbors but also built-in listeners with a lower priority. On `rpc.pre_execute`, `rpc.pre_response` and `rpc.error` this can leave the request without a response ā do not stop these events unless you build the response yourself.
63
+
* **An exception from a listener** is turned into an error response. In a single HTTP request it does not go through `rpc.error` (see [Open issues](/docs/api/json-rpc-bundle/developers/known_issues/open)).
64
+
* **A cached response** (`#[RPC\Cache]`) is returned without execution events: nothing is dispatched after `rpc.request`.
65
+
66
+
## Context inside a listener
67
+
68
+
| What you need | Where to get it |
69
+
| --- | --- |
70
+
| Method, parameters, `id` | `$event->rpcRequest->getMethod()`, `getParams()` (without `$rpc`), `getId()` |
71
+
| Special `$rpc` parameters | `$event->rpcRequest->getRpcParams()` ā `getTimeout()`, `hasCallback()`, `getRayId()`, `ignoreCache` |
72
+
| Notification or not | `$event->rpcRequest instanceof Ufo\RpcObject\RpcNotificationRequest` |
73
+
| API version | `$event->rpcRequest->apiVersion` |
74
+
| API group | service `Ufo\JsonRpcBundle\Server\ApiGroupContext`: `getGroup()` |
75
+
| HTTP request | service `Ufo\JsonRpcBundle\Server\RequestPrepare\RequestCarrier`: `getCarrier()`, if it is `IRpcHttpCarrier` ā `getHttpRequest()` |
76
+
| Token | service `IRpcSecurity`: `getTokenHolder()->getToken()` |
77
+
| Earlier events of this request | service `RpcEventFactory`: `getEvent(Class::class)`, `getEvents(Class::class)` |
78
+
79
+
## Custom events
80
+
81
+
`RpcEventFactory::fire()` accepts any name. An unknown name is dispatched as `rpc.custom_event` (class `RpcEvent` with an `$eventData` array); the bundle itself neither dispatches nor listens to such events.
82
+
83
+
## Migrating from older versions
84
+
85
+
* Since 8.0, event classes live in `Ufo\JsonRpcBundle\EventDrivenModel\Events\*` (previously ā `Ufo\RpcObject\Events\*`).
86
+
* The `rpc.response` event was removed in 7.6 ā use `rpc.pre_response` or `rpc.post_response`.
87
+
* Since 10.3, the bundle does not stop propagation of `kernel.terminate` / `console.terminate`, so the application's terminate listeners also run after RPC requests.