Постановка задач в очередь Laravel сторонними сервисами

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

При работе над проектом (будь то хайповые микросервисы или монолит) довольно часто возникает ситуация, когда необходимо, чтобы один сервис поставил задачу для другого сервиса. Задача довольно тривиальная, если на обеих сторонах используется один и тот же фреймворк. Но все становится намного интересней, когда на стороне подписчика допустим Laravel со своим дефолтным форматом, а на стороне издателя что‑то модное на Go.

Пример дефолтного формата Laravel
{
  "uuid": "59f3007b-e63c-4c71-b298-885563664cd6",
  "displayName": "App\\Jobs\\ProcessPodcast",
  "job": "Illuminate\\Queue\\CallQueuedHandler@call",
  "maxTries": null,
  "maxExceptions": null,
  "failOnTimeout": false,
  "backoff": null,
  "timeout": null,
  "retryUntil": null,
  "data": {
    "commandName": "App\\Jobs\\ProcessPodcast",
    "command": "O:23:\"App\\Jobs\\ProcessPodcast\":1:{s:11:\"stringParam\";s:12:\"abcdef012345\";}"
  }
}


Довольно странно спихнуть формирование подобного payload на другую комманду разработчиков. Из очевидных недостатокв можно выделить не только жесткую привязку к формату Laravel, но еще и явное перечисление задействованных классов. Поэтому рассматриваем следующее решение, которое первым приходит на ум: свой хандлер, который научим понимать тот формат, который согласуем.

Предположим, что удалось согласовать нечто подобное
{
  "uuid": "59f3007b-e63c-4c71-b298-885563664cd3",
  "job": "EXAMPLE",
  "data": {
    "type": "TYPE_TEST",
    "params": {
      "stringParam": "tabcdef012345"
    }
  }
}

Но, чтобы не закапываться в программировании изобретая очередной велосипед, попробуем воспользоваться средствами сервис‑контейра.

uuid

Думаю с этой пропертей все понятно и без пояснений. Поэтому едем дальше.

job

В данном случае, мы замаскировали Illuminate\\Queue\\CallQueuedHandler@call под EXAMPLE. В сервис‑контейнере не достаточно будет просто указать EXAMPLE как синоним для класса Illuminate\Queue\CallQueuedHandler, поскольку Laravel при обработке очереди попробует вызвать метод fire, если другой не указан явно. Поэтому просто унаследуемся и расширим базовый класс нужным методом.

<?php

declare(strict_types=1);

namespace App\Providers;

use App\QueueHandler;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public $bindings = [
        // app()->bind(QueueHandler::NAME, QueueHandler::class);
        QueueHandler::NAME => QueueHandler::class
    ];
}
<?php

declare(strict_types=1);

namespace App;

use Illuminate\Contracts\Queue\Job;
use Illuminate\Queue\CallQueuedHandler;

class QueueHandler extends CallQueuedHandler
{
    public const NAME = 'EXAMPLE';
    public const JOB_CLASS = 'type';
    public const JOB_PARAMS = 'params';

    public function fire(Job $job, array $data): void {
        $this->call($job, $data);
    }

    protected function getCommand(array $data)
    {
        return $this->container->make(
            $data[self::JOB_CLASS],
            is_array($data[self::JOB_PARAMS] ?? null) ? $data[self::JOB_PARAMS] : []
        );
    }
}

data

Выше, в классе QueueHandler мы еще переопределили метод getCommand, чтобы резолвинг джобы взять в свои руки. Осталось дело за малым — связать TYPE_TEST с нашей джобой App\Jobs\ProcessPodcast через какой‑нибудь ServiceProvider.

<?php

app()->bind('TYPE_TEST', \App\Jobs\ProcessPodcast::class);

Заключение

Как итог, получаем довольно гибкий формат, который легко воспрпнимается сторонними разработчиками.

Простая кастомизация на стороне Laravel без изменений кода других сервисов.

Уменьшение объема гоняемых по сети данных.

Источник: https://habr.com/ru/articles/748288/


Интересные статьи

Интересные статьи

Любое большое дело состоит из огромного количества крошечных задач, поочерёдно выполняя которые мы постепенно приближаемся к конечному результату масштабного проекта. Мы в процессе создания браузера и...
Мы уже рассказывали о том, как применили семейство генеративных нейросетей YaLM для подготовки ответов в Поиске, Алисе или даже в Балабобе. Главная особенность наших моделей — метод few-shot learnin...
Всем привет! В данной статье пройдемся по двум задачам, взятым с leetcode.com из списка часто встречаемых задач на собеседованиях в FAANG:1. Guess the word2. Number of Good Ways to Split a StringЯ ...
Сегодня мы хотим поделиться нашими компетенциями и знаниями в области машинного обучения в графике и показать, как технологии позволяют упростить многие процессы, при этом не заменяя, а дополняя деяте...
Из цикла "Микросервисы или смерть"Решаемая проблема: монолитное приложение на Node.js раньше, в развернутом состоянии, занимало 0.2 Гб всего. Теперь же, разбитое на 33 ми...