94 lines
2.7 KiB
PHP
94 lines
2.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace app\common\service;
|
|
|
|
use support\Redis;
|
|
use Throwable;
|
|
|
|
/**
|
|
* 通过 Redis 列表在不同进程间投递 WebSocket 事件。
|
|
*/
|
|
final class GameWebSocketEventBus
|
|
{
|
|
private const KEY_QUEUE = 'dfw:v1:ws:event:queue';
|
|
private const MAX_BATCH = 100;
|
|
|
|
/**
|
|
* @param array<string, mixed> $data
|
|
*/
|
|
public static function publish(string $topic, array $data): void
|
|
{
|
|
$topic = trim($topic);
|
|
if ($topic === '') {
|
|
return;
|
|
}
|
|
$payload = [
|
|
'topic' => $topic,
|
|
'event' => $topic,
|
|
'data' => $data,
|
|
'server_time' => time(),
|
|
];
|
|
$json = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
if (!is_string($json) || $json === '') {
|
|
return;
|
|
}
|
|
try {
|
|
Redis::lPush(self::KEY_QUEUE, $json);
|
|
} catch (Throwable) {
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return list<array{topic:string,event:string,data:array<string,mixed>,server_time:int}>
|
|
*/
|
|
public static function popBatch(int $limit = self::MAX_BATCH): array
|
|
{
|
|
if ($limit <= 0) {
|
|
return [];
|
|
}
|
|
if ($limit > self::MAX_BATCH) {
|
|
$limit = self::MAX_BATCH;
|
|
}
|
|
|
|
$out = [];
|
|
try {
|
|
for ($i = 0; $i < $limit; $i++) {
|
|
$raw = Redis::rPop(self::KEY_QUEUE);
|
|
if (!is_string($raw) || $raw === '') {
|
|
break;
|
|
}
|
|
$decoded = json_decode($raw, true);
|
|
if (!is_array($decoded)) {
|
|
continue;
|
|
}
|
|
$topicRaw = $decoded['topic'] ?? '';
|
|
$eventRaw = $decoded['event'] ?? '';
|
|
$dataRaw = $decoded['data'] ?? [];
|
|
$serverTimeRaw = $decoded['server_time'] ?? time();
|
|
if (!is_string($topicRaw) || trim($topicRaw) === '') {
|
|
continue;
|
|
}
|
|
$topic = trim($topicRaw);
|
|
$event = is_string($eventRaw) && trim($eventRaw) !== '' ? trim($eventRaw) : $topic;
|
|
$data = is_array($dataRaw) ? $dataRaw : [];
|
|
$serverTime = filter_var($serverTimeRaw, FILTER_VALIDATE_INT);
|
|
if ($serverTime === false || $serverTime <= 0) {
|
|
$serverTime = time();
|
|
}
|
|
$out[] = [
|
|
'topic' => $topic,
|
|
'event' => $event,
|
|
'data' => $data,
|
|
'server_time' => $serverTime,
|
|
];
|
|
}
|
|
} catch (Throwable) {
|
|
return $out;
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
}
|