SystemNotificationSendItemJob.php 3.87 KB
<?php

namespace App\Jobs;

use App\Enums\NotificationStatusEnum;
use App\Helpers\IMHelper;
use App\Http\Container\AppSection\Controllers\NotificationController;
use App\Models\Notification;
use Arr;
use Illuminate\Bus\Batchable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Redis;
use URL;

class SystemNotificationSendItemJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Batchable;

    public Notification $notification;

    public Collection $collection;

    /**
     * @param \App\Models\Notification                 $notification
     * @param \Illuminate\Database\Eloquent\Collection $collection
     */
    public function __construct(Notification $notification, Collection $collection)
    {
        $this->notification = $notification;
        $this->collection   = $collection;
        $this->queue        = 'im';
    }

    /**
     * @throws \Illuminate\Contracts\Redis\LimiterTimeoutException
     */
    public function handle(): void
    {
        if ($this->batch()?->cancelled()) {
            return;
        }

        Redis::throttle('im-batch-send')->allow(30)->every(60)->then(function () {
            $this->collection->toQuery()->update(['status' => NotificationStatusEnum::PROCESSING, 'send_at' => now()->toDateTimeString()]);

            $result = IMHelper::sendBatchChatMessage(IMHelper::SYSTEM_USER, $this->collection->pluck('user_id')->toArray(), [
                "MsgBody"         => [
                    IMHelper::createCustomMessage([
                        "Data" => [
                            'businessID'         => 'system_notice',
                            'notification_id'    => $this->notification->getKey(),
                            'notification_class' => 'system_notification',
                            'type'               => (int)$this->notification->getAttribute('type'),
                            'title'              => $this->notification->getAttribute('title'),
                            'cover'              => $this->notification->getAttribute('cover'),
                            'content'            => $this->notification->getAttribute('content'),
                            'link_type'          => $this->notification->getAttribute('link_type'),
                            'link_id'            => (int)$this->notification->getAttribute('link_id'),
                            'link_url'           => URL::action([NotificationController::class, 'show'], [$this->notification->getKey()]),
                        ],
                        "Desc" => $this->notification->getAttribute('title'),
                    ], ['is_alert' => $this->notification->getAttribute('is_alert') ?? 0]),
                ],
                "CloudCustomData" => [],
                "OfflinePushInfo" => IMHelper::createOfflineMessage('系统消息', $this->notification->getAttribute('title'))
            ]);

            if ($result->json('ActionStatus') === 'FAIL') {
                $this->collection->toQuery()->update(['status' => NotificationStatusEnum::FAIL, 'msg_key' => '']);
            } else {
                $this->collection->toQuery()->update(['status' => NotificationStatusEnum::SUCCESS, 'msg_key' => $result->json('MsgKey', '')]);
                if ($failAccount = Arr::pluck($result->json('ErrorList', []), 'To_Account')) {
                    $this->notification->items()
                        ->whereIn('user_id', Arr::map($failAccount, static fn($item) => IMHelper::accountToUserKey($item)))
                        ->update(['status' => NotificationStatusEnum::FAIL, 'msg_key' => '']);
                }
            }
        }, function () {
            $this->release(1);
        });
    }
}