docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api
en/docs/api/json-rpc-bundle/functionality/events/post_response.md
new file +101
−0
rpc.post_response
Event name
rpc.post_response
Constant
RpcEvent::POST_RESPONSE
Class
RpcPostResponseEvent
Properties
RpcResponse $response, RpcRequest $rpcRequest, Service $service
The client has already received the response. This is the event for heavy work that must not delay the response: auditing, sending emails, cache invalidation, integrations.
When it is dispatched
Once per successfully executed request:
| Source | Moment |
|---|---|
| HTTP | kernel.terminate, after fastcgi_finish_request() (under PHP-FPM the client does not wait) |
| Console, batch child processes | console.terminate |
| Inline batch | right after each item |
RpcExecutor (adapters) |
kernel.terminate of the main request |
Not dispatched for an error response, a cached response and for messages from Symfony Messenger.
An exception in a listener is logged and does not affect other listeners or other requests.
Built-in listeners
| Priority | Listener | What it does |
|---|---|---|
| 1000 | CacheRelationsEventListener |
Invalidates and warms up the cache according to #[RPC\CacheRelation] |
| 10 | AsyncServerEventListener::processAsync |
Executes notifications and requests with $rpc.callback (or hands them to a detached process) |
Do not stop propagation with a priority above 10: notifications and callback requests will then never be executed.
For notifications and callback, $event->response is a placeholder; after priority 10 the real result is available in $event->rpcRequest->getResponseObject().
What can be changed
Nothing in the response — it has already been sent. Only side effects.
Usage examples
Change auditing
#[AsEventListener(RpcEvent::POST_RESPONSE)]
final class AuditListener
{
public function __construct(private AuditLog $audit, private ApiGroupContext $groups) {}
public function __invoke(RpcPostResponseEvent $event): void
{
$this->audit->record(
method: $event->service->name,
params: $event->rpcRequest->getParams(),
group: $this->groups->getGroup(),
);
}
}
Post-response integration
Send a webhook to a partner or sync data with a CRM without delaying the client. For very long operations, it is better to hand the work off to a Symfony Messenger queue.
At this point the Symfony HTTP request has already been popped from the RequestStack. If you need its headers, take them from RequestCarrier (getCarrier()->getHttpRequest() for IRpcHttpCarrier).