AdminRealtimeAgentApplications.php 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. <?php
  2. namespace App\Services\AdminRealtime;
  3. use Illuminate\Support\Facades\Cache;
  4. use Illuminate\Support\Facades\DB;
  5. use Illuminate\Support\Facades\Log;
  6. /**
  7. * 会员代理申请由 melbet_sport-api 直接插入 agent_applications,不经 bot-28 模型钩子。
  8. * relay 每轮按主键游标找出新申请并登记 created 事件;审核等修改在 bot-28 内经模型钩子登记。
  9. *
  10. * 游标存缓存:首次运行(或缓存丢失)从当前最大 id 开始,不补推历史申请;
  11. * 列表与待处理角标不受影响,前端重连时会重新拉列表。
  12. */
  13. final class AdminRealtimeAgentApplications
  14. {
  15. private const CURSOR = 'admin_realtime:agent_applications_cursor';
  16. private const BATCH = 200;
  17. public static function scan(): void
  18. {
  19. if (!config('admin_realtime.enabled')) return;
  20. try {
  21. $cursor = Cache::get(self::CURSOR);
  22. if ($cursor === null) {
  23. Cache::forever(self::CURSOR, (int) DB::table('agent_applications')->max('id'));
  24. return;
  25. }
  26. $ids = DB::table('agent_applications')->where('id', '>', (int) $cursor)
  27. ->orderBy('id')->limit(self::BATCH)->pluck('id')->map(static fn($id): int => (int) $id)->all();
  28. if (!$ids) return;
  29. // 先登记再推进游标;登记失败抛出,下轮重试(最多重复,不会漏)。
  30. $now = now('Asia/Shanghai')->format('Y-m-d H:i:s');
  31. DB::table('admin_realtime_events')->insert(array_map(static fn(int $id): array => [
  32. 'resource' => 'agent_applications', 'resource_id' => (string) $id, 'action' => 'created',
  33. 'source' => 'melbet_sport-api', 'created_at' => $now,
  34. ], $ids));
  35. Cache::forever(self::CURSOR, max($ids));
  36. } catch (\Throwable $e) {
  37. Log::channel('realtime')->error('admin_realtime_agent_application_scan_failed', ['error' => $e->getMessage()]);
  38. }
  39. }
  40. }