Черги та cron

← Черги та cron

Ashterix

docs(articles): Magento and Symfony examples side by side, request lifecycle as a Mermaid diagram

uk/articles/magento-to-symfony/infrastructure/async.md +12 −2

Черги та cron

Magento · чотири XML і publisher

<!-- communication.xml -->
<topic name="vendor.product.reindex" request="int"/>
<!-- queue_publisher.xml, queue_topology.xml,
     queue_consumer.xml — ще три файли -->
$this->publisher->publish('vendor.product.reindex', $productId);

class ReindexConsumer
{
    public function process(int $productId): void 
    { 
        // 
    }
}

Symfony · повідомлення, обробник, маршрут

final class ReindexProduct
{
    public function __construct(public readonly int $productId) {}
}

#[AsMessageHandler]
final class ReindexProductHandler
{
    public function __invoke(ReindexProduct $message): void 
    { 
        // 
    }
}

$this->bus->dispatch(new ReindexProduct($product->getId()));

Magento · чотири XML і publisher

<!-- communication.xml -->
<topic name="vendor.product.reindex" request="int"/>
<!-- queue_publisher.xml, queue_topology.xml,
     queue_consumer.xml — ще три файли -->
$this->publisher->publish('vendor.product.reindex', $productId);

class ReindexConsumer
{
    public function process(int $productId): void 
    { 
        // 
    }
}

Symfony · повідомлення, обробник, маршрут

final class ReindexProduct
{
    public function __construct(public readonly int $productId) {}
}

#[AsMessageHandler]
final class ReindexProductHandler
{
    public function __invoke(ReindexProduct $message): void 
    { 
        // 
    }
}

$this->bus->dispatch(new ReindexProduct($product->getId()));

Symfony · config/packages/messenger.yaml

framework:
    messenger:
        failure_transport: failed
        transports:
            async:
                dsn: '%env(MESSENGER_TRANSPORT_DSN)%'   # doctrine://, amqp://, redis://
                retry_strategy: { max_retries: 3, delay: 1000, multiplier: 2 }
            failed: 'doctrine://default?queue_name=failed'
        routing:
            App\Message\ReindexProduct: async
  • Без рядка в routing повідомлення обробиться синхронно, одразу при dispatch(). Зручно в тестах і для поступового переходу.
  • Воркер: bin/console messenger:consume async --time-limit=3600 --memory-limit=256M під supervisor або systemd.
  • Провалені після ретраїв повідомлення лежать у failed: messenger:failed:show, messenger:failed:retry.
  • У повідомлення кладуть id і скаляри, а не сутності: повідомлення серіалізується, а сутність у воркері треба перечитати.

crontab.xml → Scheduler

Magento · crontab.xml

<group id="default">
    <job name="vendor_cleanup_quotes"
         instance="Vendor\Sales\Cron\CleanupQuotes"
         method="execute">
        <schedule>0 3 * * *</schedule>
    </job>
</group>

Symfony · symfony/scheduler

use Symfony\Component\Scheduler\Attribute\AsCronTask;

#[AsCronTask('0 3 * * *')]
final class CleanupExpiredQuotes
{
    public function __invoke(): void 
    { 
        // 
    }
}

# запуск розкладу — це воркер Messenger:
# bin/console messenger:consume scheduler_default

Magento · crontab.xml

<group id="default">
    <job name="vendor_cleanup_quotes"
         instance="Vendor\Sales\Cron\CleanupQuotes"
         method="execute">
        <schedule>0 3 * * *</schedule>
    </job>
</group>

Symfony · symfony/scheduler

use Symfony\Component\Scheduler\Attribute\AsCronTask;

#[AsCronTask('0 3 * * *')]
final class CleanupExpiredQuotes
{
    public function __invoke(): void 
    { 
        // 
    }
}

# запуск розкладу — це воркер Messenger:
# bin/console messenger:consume scheduler_default

Альтернатива без Scheduler — звичайна консольна команда в системному crontab. Для задач, які не можна запускати паралельно на кількох серверах, додайте компонент Lock.