rpc.request

← rpc.request

Ashterix

docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api

en/docs/api/json-rpc-bundle/functionality/events/request.md new file +113 āˆ’0

1 + # rpc.request
2 +
3 + ::::::block class="floatinginfobox floatinginfobox--fit"
4 + :::::columns border zebra
5 + ::::row
6 + :::col width="40%"
7 + **Event name**
8 + :::
9 + :::col
10 + `rpc.request`
11 + :::
12 + ::::
13 + ::::row
14 + :::col width="40%"
15 + **Constant**
16 + :::
17 + :::col
18 + `RpcEvent::REQUEST`
19 + :::
20 + ::::
21 + ::::row
22 + :::col width="40%"
23 + **Class**
24 + :::
25 + :::col
26 + `RpcRequestEvent`
27 + :::
28 + ::::
29 + ::::row
30 + :::col width="40%"
31 + **Properties**
32 + :::
33 + :::col
34 + `RpcRequest $rpcRequest`
35 + :::
36 + ::::
37 + ::::row
38 + :::col width="40%"
39 + **Built-in listeners**
40 + :::
41 + :::col
42 + none
43 + :::
44 + ::::
45 + :::::
46 + ::::::
47 +
48 + The first RPC event of a request: dispatched after JSON parsing and the token and `jsonrpc` version checks, but **before** the cache check and the method call.
49 +
50 + ## When it is dispatched
51 +
52 + * Single HTTP request and console call — once.
53 + * Batch: for each item. In process mode — in the child process, not in the parent.
54 + * Notifications and `$rpc.callback` — once on receipt; it is not dispatched again during deferred execution of the method.
55 + * Calls via `RpcExecutor` (REST and MCP adapters) — for each request.
56 +
57 + **Not dispatched** for messages from Symfony Messenger, for cache warm-up requests and for requests rejected earlier (invalid JSON, token error).
58 +
59 + ## What can be changed
60 +
61 + * Assigning a new `$event->rpcRequest` **has no effect** — the handler works with its own reference to the request.
62 + * The request object itself can be modified. `$event->rpcRequest->setError($exception)` makes the request fail before the method is called (checked on `rpc.pre_execute`). This does not affect a cached response or the receipt of notifications/callback.
63 + * An exception from a listener returns an error to the client.
64 +
65 + ## Usage examples
66 +
67 + ### Tracing
68 +
69 + Bind the request to a tracing ID — `rayId` from the special parameters or a custom header:
70 +
71 + ```php
72 + #[AsEventListener(RpcEvent::REQUEST)]
73 + final class TraceListener
74 + {
75 + public function __construct(private LoggerInterface $logger) {}
76 +
77 + public function __invoke(RpcRequestEvent $event): void
78 + {
79 + $request = $event->rpcRequest;
80 + $this->logger->info('rpc.request', [
81 + 'method' => $request->getMethod(),
82 + 'id' => $request instanceof RpcNotificationRequest ? null : $request->getId(),
83 + 'ray_id' => $request->getRpcParams()?->getRayId(),
84 + 'version' => $request->apiVersion,
85 + ]);
86 + }
87 + }
88 + ```
89 +
90 + ### Maintenance
91 +
92 + Temporarily reject calls to specific methods (for example, during a migration):
93 +
94 + ```php
95 + #[AsEventListener(RpcEvent::REQUEST)]
96 + final class MaintenanceListener
97 + {
98 + public function __construct(private FeatureFlags $flags) {}
99 +
100 + public function __invoke(RpcRequestEvent $event): void
101 + {
102 + if ($this->flags->isFrozen($event->rpcRequest->getMethod())) {
103 + $event->rpcRequest->setError(new RpcLogicException('Method is temporarily unavailable'));
104 + }
105 + }
106 + }
107 + ```
108 +
109 + ### Other ideas
110 +
111 + * a method call counter (per-client rate limiting);
112 + * collecting usage statistics for deprecated methods;
113 + * checking additional access conditions for a method (role, client plan).