fix(hot-reload): keep the event dispatcher in the message child
The dev hot reload forgot the `events` instance, so the container rebuilt an empty dispatcher and every listener the service providers registered was gone for that message. Events fired from WS controllers reached nobody (a shop's "order paid" mails and invoice silently never happened in dev). Model observers kept working, which hid it: Eloquent holds its own reference to the old dispatcher. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ca90561c9d
commit
9dc34d5c10
|
|
@ -521,14 +521,10 @@ class Handler implements MessageComponentInterface
|
|||
// Validator refresh failed, continue anyway
|
||||
}
|
||||
|
||||
// 9. Clear event dispatcher cache (for fresh event/listener bindings)
|
||||
try {
|
||||
if ($container->bound('events')) {
|
||||
$container->forgetInstance('events');
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// Events refresh failed, continue anyway
|
||||
}
|
||||
// 9. The event dispatcher is deliberately KEPT: listeners are registered
|
||||
// once by the service providers (Event::listen in boot()), which never
|
||||
// run again in this child. A forgotten instance would be rebuilt empty
|
||||
// and every event fired from the controller would reach no listener.
|
||||
|
||||
// 10. Clear WebSocket ControllerResolver cache for fresh controller loading
|
||||
ControllerResolver::clearCache();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace BlaxSoftware\LaravelWebSockets\Test;
|
||||
|
||||
use BlaxSoftware\LaravelWebSockets\Websocket\Handler;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
/**
|
||||
* Regression guard: the dev hot reload in the message child used to forget the
|
||||
* `events` instance. The container then built an empty dispatcher, and every
|
||||
* listener the service providers had registered (Event::listen in boot()) was
|
||||
* gone for that message, so events fired from a WS controller reached nobody
|
||||
* (e.g. a shop's "order paid" mails and invoice never happened in dev).
|
||||
*/
|
||||
class HotReloadKeepsListenersTest extends TestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$this->setHotReload(null);
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
private function setHotReload(?bool $on): void
|
||||
{
|
||||
$flag = new \ReflectionProperty(Handler::class, 'hotReload');
|
||||
$flag->setAccessible(true);
|
||||
$flag->setValue(null, $on);
|
||||
}
|
||||
|
||||
public function test_listeners_registered_at_boot_survive_the_hot_reload()
|
||||
{
|
||||
$heard = 0;
|
||||
Event::listen('shop.order-paid', function () use (&$heard) {
|
||||
$heard++;
|
||||
});
|
||||
|
||||
$this->setHotReload(true);
|
||||
$reload = new \ReflectionMethod($this->wsHandler, 'hotReloadChild');
|
||||
$reload->setAccessible(true);
|
||||
$reload->invoke($this->wsHandler);
|
||||
|
||||
event('shop.order-paid');
|
||||
|
||||
$this->assertSame(1, $heard);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue