AdminRealtime.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. <?php
  2. namespace App\Services\AdminRealtime;
  3. use Illuminate\Database\Eloquent\Model;
  4. use Illuminate\Support\Facades\DB;
  5. use Illuminate\Support\Facades\Log;
  6. /**
  7. * 后台实时推送事件登记。
  8. *
  9. * 只登记「哪张表的哪条记录发生了什么」,事务提交后写入 admin_realtime_events;
  10. * 列表行由推送网关拉取时按对应列表接口的口径解析(见 AdminRealtimeRows)。
  11. * 登记失败只记 realtime 日志,绝不抛出,不影响下单、充值等主业务。
  12. */
  13. final class AdminRealtime
  14. {
  15. /** 监听的表 => 仅这些列变化时不推送(例如通知标记、更新时间) */
  16. public const RESOURCES = [
  17. 'sport_order' => ['update_time'],
  18. 'lhc_order' => ['updated_at'],
  19. 'sport_game_order' => ['updated_at'],
  20. 'jisu_game_order' => ['updated_at'],
  21. 'third_game_orders' => ['updated_at'],
  22. 'bets' => ['updated_at'],
  23. 'recharges' => ['updated_at', 'is_send'],
  24. 'payment_orders' => ['updated_at', 'is_send'],
  25. 'withdraws' => ['updated_at', 'is_send'],
  26. 'manual_audits' => ['updated_at'],
  27. 'users' => [],
  28. ];
  29. /** 用户列表只推新增;在线状态由 OnlineStatusScanner 产生 */
  30. public const USER_ONLINE = 'user_online';
  31. public static function captureModel(Model $model, string $action): void
  32. {
  33. $table = $model->getTable();
  34. if (!array_key_exists($table, self::RESOURCES)) return;
  35. if ($table === 'users' && $action !== 'created') return;
  36. if ($action === 'updated' && !array_diff(array_keys($model->getChanges()), self::RESOURCES[$table])) return;
  37. self::record($table, $model->getKey(), $action);
  38. }
  39. /**
  40. * @param string $resource 表名(不含前缀)或 user_online
  41. * @param int|string|array $ids 记录主键
  42. * @param string $action created / updated / deleted / online / offline
  43. */
  44. public static function record(string $resource, $ids, string $action = 'updated'): void
  45. {
  46. if (!config('admin_realtime.enabled')) return;
  47. $ids = array_values(array_unique(array_filter(array_map('strval', (array) $ids), static fn(string $id): bool => $id !== '')));
  48. if (!$ids) return;
  49. $write = static function () use ($resource, $ids, $action): void {
  50. try {
  51. $now = now('Asia/Shanghai')->format('Y-m-d H:i:s');
  52. foreach (array_chunk($ids, 500) as $chunk) {
  53. DB::table('admin_realtime_events')->insert(array_map(static fn(string $id): array => [
  54. 'resource' => $resource, 'resource_id' => $id, 'action' => $action, 'source' => 'bot-28', 'created_at' => $now,
  55. ], $chunk));
  56. }
  57. } catch (\Throwable $e) {
  58. Log::channel('realtime')->error('admin_realtime_record_failed', [
  59. 'resource' => $resource, 'action' => $action, 'count' => count($ids), 'error' => $e->getMessage(),
  60. ]);
  61. }
  62. };
  63. // 事务内调用时等提交后再写,回滚则丢弃;不在事务内立即写
  64. try {
  65. DB::afterCommit($write);
  66. } catch (\Throwable $e) {
  67. $write();
  68. }
  69. }
  70. }