8000 feature #29312 [EventDispatcher] Split events across requests (ro0NL) · symfony/symfony@50a5dfd · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 50a5dfd

Browse files
committed
feature #29312 [EventDispatcher] Split events across requests (ro0NL)
This PR was squashed before being merged into the 4.3-dev branch (closes #29312). Discussion ---------- [EventDispatcher] Split events across requests | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no <!-- see https://symfony.com/bc --> | Deprecations? | no | Tests pass? | yes <!-- please add some, will be required by reviewers --> | Fixed tickets | #24275 | License | MIT | Doc PR | symfony/symfony-docs#... <!-- required for new features --> Split events per request, as currently a profiled sub-request includes all events. Follows same approach how logs are split in #23659. Commits ------- c3477ba [EventDispatcher] Split events across requests
2 parents aa5b6f9 + c3477ba commit 50a5dfd

File tree

6 files changed

+57
-21
lines changed

6 files changed

+57
-21
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
<service id="data_collector.events" class="Symfony\Component\HttpKernel\DataCollector\EventDataCollector">
2929
<tag name="data_collector" template="@WebProfiler/Collector/events.html.twig" id="events" priority="290" />
3030
<argument type="service" id="debug.event_dispatcher" on-invalid="ignore" />
31+
<argument type="service" id="request_stack" on-invalid="ignore" />
3132
</service>
3233

3334
<service id="data_collector.logger" class="Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector">

src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<argument type="service" id="debug.event_dispatcher.inner" />
1313
<argument type="service" id="debug.stopwatch" />
1414
<argument type="service" id="logger" on-invalid="null" />
15+
<argument type="service" id="request_stack" on-invalid="null" />
1516
</service>
1617

1718
<service id="debug.controller_resolver" decorates="controller_resolver" class="Symfony\Component\HttpKernel\Controller\TraceableControllerResolver">

src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php

Lines changed: 38 additions & 15 deletions
265
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313

1414
use Psr\EventDispatcher\StoppableEventInterface;
1515
use Psr\Log\LoggerInterface;
16+
use Symfony\Component\BrowserKit\Request;
1617
use Symfony\Component\EventDispatcher\Event;
1718
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
1819
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
1920
use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy;
21+
use Symfony\Component\HttpFoundation\RequestStack;
2022
use Symfony\Component\Stopwatch\Stopwatch;
2123
use Symfony\Contracts\EventDispatcher\Event as ContractsEvent;
2224

@@ -36,14 +38,17 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
3638
private $dispatcher;
3739
private $wrappedListeners;
3840
private $orphanedEvents;
41+
private $requestStack;
42+
private $currentRequestHash = '';
3943

40-
public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null)
44+
public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null, RequestStack $requestStack = null)
4145
{
4246
$this->dispatcher = LegacyEventDispatcherProxy::decorate($dispatcher);
4347
$this->stopwatch = $stopwatch;
4448
$this->logger = $logger;
4549
$this->wrappedListeners = [];
4650
$this->orphanedEvents = [];
51+
$this->requestStack = $requestStack;
4752
}
4853

4954
/**
@@ -133,6 +138,7 @@ public function dispatch($event/*, string $eventName = null*/)
133138
$this->callStack = new \SplObjectStorage();
134139
}
135140

141+
$currentRequestHash = $this->currentRequestHash = $this->requestStack && ($request = $this->requestStack->getCurrentRequest()) ? spl_object_hash($request) : '';
136142
$eventName = 1 < \func_num_args() ? \func_get_arg(1) : null;
137143

138144
if (\is_object($event)) {
@@ -168,6 +174,7 @@ public function dispatch($event/*, string $eventName = null*/)
168174
$this->afterDispatch($eventName, $event);
169175
}
170176
} finally {
177+
$this->currentRequestHash = $currentRequestHash;
171178
$this->postProcess($eventName);
172179
}
173180

@@ -176,27 +183,33 @@ public function dispatch($event/*, string $eventName = null*/)
176183

177184
/**
178185
* {@inheritdoc}
186+
*
187+
* @param Request|null $request The request to get listeners for
179188
*/
180-
public function getCalledListeners()
189+
public function getCalledListeners(/* Request $request = null */)
181190
{
182191
if (null === $this->callStack) {
183192
return [];
184193
}
185194

195+
$hash = 1 <= \func_num_args() && null !== ($request = \func_get_arg(0)) ? spl_object_hash($request) : null;
186196
$called = [];
187197
foreach ($this->callStack as $listener) {
188-
list($eventName) = $this->callStack->getInfo();
189-
190-
$called[] = $listener->getInfo($eventName);
198+
list($eventName, $requestHash) = $this->callStack->getInfo();
199+
if (null === $hash || $hash === $requestHash) {
200+
$called[] = $listener->getInfo($eventName);
201+
}
191202
}
192203

193204
return $called;
194205
}
195206

196207
/**
197208
* {@inheritdoc}
209+
*
210+
* @param Request|null $request The request to get listeners for
198211
*/
199-
public function getNotCalledListeners()
212+
public function getNotCalledListeners(/* Request $request = null */)
200213
{
201214
try {
202215
$allListeners = $this->getListeners();
@@ -209,13 +222,15 @@ public function getNotCalledListeners()
209222
return [];
210223
}
211224

225+
$hash = 1 <= \func_num_args() && null !== ($request = \func_get_arg(0)) ? spl_object_hash($request) : null;
212226
$notCalled = [];
213227
foreach ($allListeners as $eventName => $listeners) {
214228
foreach ($listeners as $listener) {
215229
$called = false;
216230
if (null !== $this->callStack) {
217231
foreach ($this->callStack as $calledListener) {
218-
if ($calledListener->getWrappedListener() === $listener) {
232+
list(, $requestHash) = $this->callStack->getInfo();
233+
if ((null === $hash || $hash === $requestHash) && $calledListener->getWrappedListener() === $listener) {
219234
$called = true;
220235

221236
break;
@@ -237,15 +252,27 @@ public function getNotCalledListeners()
237252
return $notCalled;
238253
}
239254

240-
public function getOrphanedEvents(): array
255+
/**
256+
* @param Request|null $request The request to get orphaned events for
257+
*/
258+
public function getOrphanedEvents(/* Request $request = null */): array
241259
{
242-
return $this->orphanedEvents;
260+
if (1 <= \func_num_args() && null !== $request = \func_get_arg(0)) {
261+
return $this->orphanedEvents[spl_object_hash($request)] ?? [];
262+
}
263+
264+
if (!$this->orphanedEvents) {
+
return [];
266+
}
267+
268+
return array_merge(...array_values($this->orphanedEvents));
243269
}
244270

245271
public function reset()
246272
{
247273
$this->callStack = null;
248274
$this->orphanedEvents = [];
275+
$this->currentRequestHash = '';
249276
}
250277

251278
/**
@@ -298,7 +325,7 @@ protected function postDispatch($eventName, Event $event)
298325
private function preProcess($eventName)
299326
{
300327
if (!$this->dispatcher->hasListeners($eventName)) {
301-
$this->orphanedEvents[] = $eventName;
328+
$this->orphanedEvents[$this->currentRequestHash][] = $eventName;
302329

303330
return;
304331
}
@@ -309,7 +336,7 @@ private function preProcess($eventName)
309336
$this->wrappedListeners[$eventName][] = $wrappedListener;
310337
$this->dispatcher->removeListener($eventName, $listener);
311338
$this->dispatcher->addListener($eventName, $wrappedListener, $priority);
312-
$this->callStack->attach($wrappedListener, [$eventName]);
339+
$this->callStack->attach($wrappedListener, [$eventName, $this->currentRequestHash]);
313340
}
314341
}
315342

@@ -334,10 +361,6 @@ private function postProcess($eventName)
334361
if (null !== $this->logger) {
335362
$this->logger->debug('Notified event "{event}" to listener "{listener}".', $context);
336363
}
337-
338-
if (!isset($this->called[$eventName])) {
339-
$this->called[$eventName] = new \SplObjectStorage();
340-
}
341364
} else {
342365
$this->callStack->detach($listener);
343366
}

src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php

Lines changed: 7 additions & 2 deletions
< 10000 /tr>
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\EventDispatcher\Debug;
1313

1414
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
15+
use Symfony\Component\HttpFoundation\Request;
1516
use Symfony\Contracts\Service\ResetInterface;
1617

1718
/**
@@ -24,14 +25,18 @@ interface TraceableEventDispatcherInterface extends EventDispatcherInterface, Re
2425
/**
2526
* Gets the called listeners.
2627
*
28+
* @param Request|null $request The request to get listeners for
29+
*
2730
* @return array An array of called listeners
2831
*/
29-
public function getCalledListeners();
32+
public function getCalledListeners(/* Request $request = null */);
3033

3134
/**
3235
* Gets the not called listeners.
3336
*
37+
* @param Request|null $request The request to get listeners for
38+
*
3439
* @return array An array of not called listeners
3540
*/
36-
public function getNotCalledListeners();
41+
public function getNotCalledListeners(/* Request $request = null */);
3742
}

src/Symfony/Component/EventDispatcher/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"symfony/dependency-injection": "~3.4|~4.0",
2424
"symfony/expression-language": "~3.4|~4.0",
2525
"symfony/config": "~3.4|~4.0",
26+
"symfony/http-foundation": "^3.4|^4.0",
2627
"symfony/stopwatch": "~3.4|~4.0",
2728
"psr/log": "~1.0"
2829
},

src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
1515
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface;
1616
use Symfony\Component\HttpFoundation\Request;
17+
use Symfony\Component\HttpFoundation\RequestStack;
1718
use Symfony\Component\HttpFoundation\Response;
1819
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
1920
use Symfony\Contracts\Service\ResetInterface;
@@ -26,17 +27,21 @@
2627
class EventDataCollector extends DataCollector implements LateDataCollectorInterface
2728
{
2829
protected $dispatcher;
30+
private $requestStack;
31+
private $currentRequest;
2932

30-
public function __construct(EventDispatcherInterface $dispatcher = null)
33+
public function __construct(EventDispatcherInterface $dispatcher = null, RequestStack $requestStack = null)
3134
{
3235
$this->dispatcher = $dispatcher;
36+
$this->requestStack = $requestStack;
3337
}
3438

3539
/**
3640
* {@inheritdoc}
3741
*/
3842
public function collect(Request $request, Response $response, \Exception $exception = null)
3943
{
44+
$this->currentRequest = $this->requestStack && $this->requestStack->getMasterRequest() !== $request ? $request : null;
4045
$this->data = [
4146
'called_listeners' => [],
4247
'not_called_listeners' => [],
@@ -56,12 +61,12 @@ public function reset()
5661
public function lateCollect()
5762
{
5863
if ($this->dispatcher instanceof TraceableEventDispatcherInterface) {
59-
$this->setCalledListeners($this->dispatcher->getCalledListeners());
60-
$this->setNotCalledListeners($this->dispatcher->getNotCalledListeners());
64+
$this->setCalledListeners($this->dispatcher->getCalledListeners($this->currentRequest));
65+
$this->setNotCalledListeners($this->dispatcher->getNotCalledListeners($this->currentRequest));
6166
}
6267

6368
if ($this->dispatcher instanceof TraceableEventDispatcher) {
64-
$this->setOrphanedEvents($this->dispatcher->getOrphanedEvents());
69+
$this->setOrphanedEvents($this->dispatcher->getOrphanedEvents($this->currentRequest));
6570
}
6671

6772
$this->data = $this->cloneVar($this->data);

0 commit comments

Comments
 (0)
0