RealtimeService.php 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Broadcasting;
  4. use App\Broadcasting\Entity\WebsocketEventData;
  5. use App\Broadcasting\Events\WebsocketEvent;
  6. use Illuminate\Support\Facades\DB;
  7. use Illuminate\Support\Facades\Log;
  8. use Throwable;
  9. final class RealtimeService
  10. {
  11. /**
  12. * @param RealtimeRoom|RealtimeRoom[] $rooms
  13. * @param array<string, scalar|null> $data Payload magro (ver nota acima)
  14. */
  15. public function emit(RealtimeEvent $event, RealtimeRoom|array $rooms, array $data = []): void
  16. {
  17. $targets = collect(is_array($rooms) ? $rooms : [$rooms])
  18. ->filter()
  19. ->keyBy(fn (RealtimeRoom $room): string => $room->name)
  20. ->values();
  21. if ($targets->isEmpty()) {
  22. return;
  23. }
  24. $payload = $data + ['at' => now()->toIso8601String()];
  25. DB::afterCommit(function () use ($event, $targets, $payload): void {
  26. foreach ($targets as $room) {
  27. $this->publish($event, $room, $payload);
  28. }
  29. });
  30. }
  31. /**
  32. * Atalho para o caso mais comum: avisar um usuario especifico.
  33. */
  34. public function emitToUser(RealtimeEvent $event, ?int $userId, array $data = []): void
  35. {
  36. if (! $userId) {
  37. return;
  38. }
  39. $this->emit($event, RealtimeRoom::user($userId), $data);
  40. }
  41. /**
  42. * @param array<string, mixed> $payload
  43. */
  44. private function publish(RealtimeEvent $event, RealtimeRoom $room, array $payload): void
  45. {
  46. try {
  47. event(new WebsocketEvent(
  48. WebsocketEventData::from(
  49. room: $room->name,
  50. data: $payload,
  51. event: $event->value,
  52. )
  53. ));
  54. } catch (Throwable $e) {
  55. Log::warning('Falha ao emitir evento de tempo real', [
  56. 'event' => $event->value,
  57. 'room' => $room->name,
  58. 'message' => $e->getMessage(),
  59. ]);
  60. }
  61. }
  62. }