mdn-backend / app /Domain /Analytics /AnalyticsSessionTransitioner.php
internationalscholarsprogram's picture
feat(analytics): website analytics pipeline β€” ingestion, rollup, admin query
45dc401
Raw
History Blame Contribute Delete
1.13 kB
<?php
declare(strict_types=1);
namespace App\Domain\Analytics;
final class AnalyticsSessionTransitioner
{
private const ALLOWED = [
'open' => ['closed'],
];
public function __construct(private readonly AnalyticsSessionRepository $sessions) {}
/**
* Transition a session from open β†’ closed.
* Silently skips if the session does not exist (e.g. already expired / beacon race).
*
* @param int $durationSeconds Wall-clock seconds from started_at to close; caller computes this.
*/
public function close(string $sessionId, string $exitPath, int $durationSeconds): void
{
$session = $this->sessions->findById($sessionId);
if ($session === null) {
return;
}
$this->guard($session->status, 'closed');
$this->sessions->close($sessionId, $exitPath, $durationSeconds);
}
private function guard(string $from, string $to): void
{
$allowed = self::ALLOWED[$from] ?? [];
if (!in_array($to, $allowed, true)) {
throw new InvalidTransitionException($from, $to);
}
}
}