Как ограничить очередь на выполнение только 200 задач в час?

Для ограничения очереди на выполнение только 200 задач в час в Symfony, вы можете использовать пакет Symfony Messenger в сочетании с настройками Doctrine и Redis.

Шаг 1: Установите и настройте пакет Symfony Messenger.
- Установите пакет Symfony Messenger, используя Composer: composer require symfony/messenger
- Включите пакет Messenger в вашем файле config/bundles.php, раскомментируйте строку: SymfonyBundleMessengerBundleMessengerBundle::class => ['all' => true],
- Добавьте настройки для Messenger в вашем файле config/packages/messenger.yaml:

framework:
  messenger:
    transports:
      default: 'doctrine://default' # используйте транспорт Doctrine по умолчанию, чтобы сохранить задачи в базе данных
    routing:
      'AppMessageYourMessage': 'doctrine://default' # маршрутизируйте ваше сообщение в транспорт Doctrine

Шаг 2: Создайте класс вашего сообщения, который будет представлять вашу задачу:

<?php

namespace AppMessage;

class YourMessage
{
    private $data;

    public function __construct(array $data)
    {
        $this->data = $data;
    }

    public function getData(): array
    {
        return $this->data;
    }
}

Шаг 3: Создайте класс вашего обработчика сообщения, который будет выполнять задачу:

<?php

namespace AppMessageHandler;

use AppMessageYourMessage;

class YourMessageHandler
{
    public function __invoke(YourMessage $message)
    {
        // Ваш код выполнения задачи
    }
}

Шаг 4: Ограничьте количество обработанных сообщений в определенный промежуток времени с использованием Redis.
- Установите пакет Symfony Redis, используя Composer: composer require symfony/redis
- В файле config/packages/messenger.yaml добавьте настройки Redis:

framework:
  messenger:
    transports:
      default: 'doctrine://default'
    routing:
      'AppMessageYourMessage': 'doctrine://default'
    failure_transport: failed
    retry_strategy:
      max_retries: 3
      delay: 1000
      multiplier: 2
      max_delay: 0
    transports:
      rate_limited: 'redis://localhost/%env(REDIS_DATABASE)%' # настройки Redis, замените localhost на адрес вашего Redis сервера

- Создайте сервис, который будет отслеживать количество обработанных сообщений в Redis. Добавьте следующую конфигурацию в файлеconfig/services.yaml:

services:
  AppServiceLimitingService:
    arguments:
      $limit: 200 # ограничьте число обработанных сообщений
      $interval: 3600 # определенный промежуток времени (в данном случае, 200 задач в час)
    tags:
      - { name: monolog.logger, channel: messenger }

- Создайте класс вашей службы для отслеживания количества обработанных сообщений:

<?php

namespace AppService;

use SymfonyComponentCacheAdapterRedisAdapter;
use SymfonyContractsCacheItemInterface;

class LimitingService
{
    private $limit;
    private $interval;
    private $cache;

    public function __construct(int $limit, int $interval)
    {
        $this->limit = $limit;
        $this->interval = $interval;
        $this->cache = new RedisAdapter(
            RedisAdapter::createConnection('redis://localhost') // настройте подключение к вашему Redis серверу
        );
    }

    public function isLimitReached(): bool
    {
        $count = $this->cache->get('job_count', function (ItemInterface $item) {
            $item->expiresAfter($this->interval);

            return 0;
        });

        if ($count >= $this->limit) {
            return true;
        }
        
        $this->cache->increment('job_count');

        return false;
    }
}

Шаг 5: Измените ваш обработчик сообщений, чтобы проверить ограничение перед выполнением задачи:

<?php

namespace AppMessageHandler;

use AppMessageYourMessage;
use AppServiceLimitingService;

class YourMessageHandler
{
    private $limitingService;

    public function __construct(LimitingService $limitingService)
    {
        $this->limitingService = $limitingService;
    }

    public function __invoke(YourMessage $message)
    {
        if ($this->limitingService->isLimitReached()) {
            throw new RuntimeException('Слишком много задач в очереди');
        }

        // Ваш код выполнения задачи
    }
}

Теперь ваша очередь будет ограничена на выполнение только 200 задач в час. Если превышено ограничение, будет выброшено исключение и задача не будет выполнена.