| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- <?php
- declare(strict_types=1);
- namespace App\Broadcasting;
- use App\Broadcasting\Entity\WebsocketEventData;
- use App\Broadcasting\Events\WebsocketEvent;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Log;
- use Throwable;
- final class RealtimeService
- {
- /**
- * @param RealtimeRoom|RealtimeRoom[] $rooms
- * @param array<string, scalar|null> $data Payload magro (ver nota acima)
- */
- public function emit(RealtimeEvent $event, RealtimeRoom|array $rooms, array $data = []): void
- {
- $targets = collect(is_array($rooms) ? $rooms : [$rooms])
- ->filter()
- ->keyBy(fn (RealtimeRoom $room): string => $room->name)
- ->values();
- if ($targets->isEmpty()) {
- return;
- }
- $payload = $data + ['at' => now()->toIso8601String()];
- DB::afterCommit(function () use ($event, $targets, $payload): void {
- foreach ($targets as $room) {
- $this->publish($event, $room, $payload);
- }
- });
- }
- /**
- * Atalho para o caso mais comum: avisar um usuario especifico.
- */
- public function emitToUser(RealtimeEvent $event, ?int $userId, array $data = []): void
- {
- if (! $userId) {
- return;
- }
- $this->emit($event, RealtimeRoom::user($userId), $data);
- }
- /**
- * @param array<string, mixed> $payload
- */
- private function publish(RealtimeEvent $event, RealtimeRoom $room, array $payload): void
- {
- try {
- event(new WebsocketEvent(
- WebsocketEventData::from(
- room: $room->name,
- data: $payload,
- event: $event->value,
- )
- ));
- } catch (Throwable $e) {
- Log::warning('Falha ao emitir evento de tempo real', [
- 'event' => $event->value,
- 'room' => $room->name,
- 'message' => $e->getMessage(),
- ]);
- }
- }
- }
|