| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- <?php
- namespace App\Services\AdminRealtime;
- use App\Constants\HttpStatus;
- use App\Http\Controllers\admin\Online;
- use App\Http\Controllers\admin\PaymentOrder;
- use Illuminate\Http\JsonResponse;
- use Illuminate\Support\Facades\Cache;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Log;
- use RuntimeException;
- /** 全量统计按变化登记事件,覆盖跨仓库写入、在线平台变化及统计时间窗口到期。 */
- final class AdminRealtimeSummaries
- {
- public const DEFINITIONS = [
- 'online_platform_count' => ['admin.stats.platform_count', Online::class, 'platformCount'],
- 'payment_unprocessed' => ['admin.stats.unprocessed', PaymentOrder::class, 'unProcessed'],
- ];
- public static function read(string $resource): array
- {
- [, $controller, $method] = self::DEFINITIONS[$resource];
- // 复用 HTTP 端点本身,统计字段、筛选条件和时间窗口只有一个实现。
- $response = app()->call([app()->make($controller), $method]);
- $body = $response instanceof JsonResponse ? $response->getData(true) : [];
- if (($body['code'] ?? null) !== HttpStatus::OK || !is_array($body['data'] ?? null)) {
- throw new RuntimeException($controller . '@' . $method . ' failed: ' . ($body['msg'] ?? 'invalid response'));
- }
- return $body['data'];
- }
- public static function scan(): void
- {
- if (!config('admin_realtime.enabled')) return;
- $interval = max(1, (int) config('admin_realtime.summary_scan_seconds', 5));
- foreach (array_keys(self::DEFINITIONS) as $resource) {
- try {
- if (!Cache::add('admin_realtime:summary_scan:' . $resource, 1, $interval)) continue;
- $signature = hash('sha256', json_encode(self::read($resource), JSON_THROW_ON_ERROR));
- $key = 'admin_realtime:summary_snapshot:' . $resource;
- if (Cache::get($key) === $signature) continue;
- // 必须先确认事件登记成功再记住快照;失败或崩溃最多重复,不会吞掉变化。
- if (!DB::table('admin_realtime_events')->insert([
- 'resource' => $resource, 'resource_id' => '1', 'action' => 'updated',
- 'source' => 'bot-28', 'created_at' => now('Asia/Shanghai')->format('Y-m-d H:i:s'),
- ])) throw new RuntimeException('Summary event registration failed');
- Cache::forever($key, $signature);
- } catch (\Throwable $e) {
- Log::channel('realtime')->error('admin_realtime_summary_scan_failed', [
- 'resource' => $resource, 'error' => $e->getMessage(),
- ]);
- }
- }
- }
- }
|