feat: 添加 Laravel Reverb 支持,更新 .env.example 文件以配置 WebSocket,增强彩票调度功能,更新 API 路由以支持期号管理与结果发布
This commit is contained in:
80
app/Services/Draw/LotteryHallRealtimeBroadcaster.php
Normal file
80
app/Services/Draw/LotteryHallRealtimeBroadcaster.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Draw;
|
||||
|
||||
use App\Events\DrawCountdownBroadcast;
|
||||
use App\Events\DrawResultPublishedBroadcast;
|
||||
use App\Events\DrawStatusChangeBroadcast;
|
||||
|
||||
/**
|
||||
* 对齐界面文档 §2.1:`draw.countdown`、`draw.status_change`、`result.published`(频道 `lottery-hall`)。
|
||||
*/
|
||||
final class LotteryHallRealtimeBroadcaster
|
||||
{
|
||||
public function __construct(
|
||||
private readonly DrawHallSnapshotBuilder $snapshot,
|
||||
) {}
|
||||
|
||||
/** 每秒调度:`draw.countdown` */
|
||||
public function countdownPulse(): void
|
||||
{
|
||||
if (! $this->driverSupportsRealtime()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $this->snapshot->build();
|
||||
$ms = (int) floor(microtime(true) * 1000);
|
||||
|
||||
broadcast(new DrawCountdownBroadcast($data, $ms));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tick 首尾对比:**数据库**当期指纹({@see DrawHallSnapshotBuilder::hallTargetFingerprint})变了再发,
|
||||
* 载荷仍为 {@see DrawHallSnapshotBuilder::build()}(含未到 tick 时对 `open` 的展示规范化)。
|
||||
*/
|
||||
public function notifyStatusChangeIfHallDbChanged(?array $fpBefore, ?array $fpAfter, ?array $snapshotPayload): void
|
||||
{
|
||||
if (! $this->driverSupportsRealtime()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (($fpBefore['draw_no'] ?? null) === ($fpAfter['draw_no'] ?? null)
|
||||
&& ($fpBefore['status'] ?? null) === ($fpAfter['status'] ?? null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->notifyStatusChange($snapshotPayload);
|
||||
}
|
||||
|
||||
/** `draw.status_change`(管理端发布后等不与 tick 同路径时使用)。 */
|
||||
public function notifyStatusChange(?array $data): void
|
||||
{
|
||||
if (! $this->driverSupportsRealtime()) {
|
||||
return;
|
||||
}
|
||||
|
||||
broadcast(new DrawStatusChangeBroadcast($data, (int) floor(microtime(true) * 1000)));
|
||||
}
|
||||
|
||||
/** `result.published` */
|
||||
public function notifyResultPublished(?array $data): void
|
||||
{
|
||||
if (! $this->driverSupportsRealtime()) {
|
||||
return;
|
||||
}
|
||||
|
||||
broadcast(new DrawResultPublishedBroadcast($data, (int) floor(microtime(true) * 1000)));
|
||||
}
|
||||
|
||||
private function driverSupportsRealtime(): bool
|
||||
{
|
||||
$default = config('broadcasting.default');
|
||||
if ($default === null || $default === 'null') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$driver = config("broadcasting.connections.{$default}.driver") ?? $default;
|
||||
|
||||
return ! in_array($driver, ['null', 'log'], true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user