Broadcast game_finished when a player's own timeout check catches it

Previously only the cron's timeout sweep broadcast to everyone;
check-finished (called by a player's own client the moment their
local countdown hits zero) just updated the database silently. Now
whichever path notices the timeout first broadcasts - both only act
while the session is still PLAYING, so there's no double broadcast.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Frank
2026-08-16 17:56:24 +02:00
co-authored by Claude Sonnet 5
parent 2951a39204
commit aba79251e0
+12 -1
View File
@@ -12,6 +12,8 @@ use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Mercure\HubInterface;
use Symfony\Component\Mercure\Update;
#[Route('/game/api', name: 'game_api_')] #[Route('/game/api', name: 'game_api_')]
final class GameApiController extends AbstractController final class GameApiController extends AbstractController
@@ -19,7 +21,8 @@ final class GameApiController extends AbstractController
public function __construct( public function __construct(
protected GameResponseService $gameResponseService, protected GameResponseService $gameResponseService,
private EntityManagerInterface $entityManager private EntityManagerInterface $entityManager,
private HubInterface $hub,
) { ) {
} }
@@ -46,6 +49,14 @@ final class GameApiController extends AbstractController
$session->setFinishedAt(new \DateTime()); $session->setFinishedAt(new \DateTime());
$this->entityManager->persist($session); $this->entityManager->persist($session);
$this->entityManager->flush(); $this->entityManager->flush();
try {
$topic = '/game/hub/' . $session->getId();
$this->hub->publish(new Update($topic, json_encode(['type' => 'game_finished', 'status' => 'lost'])));
} catch (\Exception $e) {
// Mercure might be down
}
$isFinished = true; $isFinished = true;
} }
} elseif ($session->getStatus() === SessionStatus::LOST || $session->getStatus() === SessionStatus::WON) { } elseif ($session->getStatus() === SessionStatus::LOST || $session->getStatus() === SessionStatus::WON) {