docs(articles): English translation of From Magento to Symfony
en/articles/magento-to-symfony/infrastructure/async.md
new file +95
โ0
1
+
# Queues and cron
2
+
3
+
**Magento** ยท four XML files and a publisher
4
+
5
+
```xml
6
+
<!-- communication.xml -->
7
+
<topic name="vendor.product.reindex" request="int"/>
8
+
<!-- queue_publisher.xml, queue_topology.xml,
9
+
queue_consumer.xml โ three more files -->
10
+
```
11
+
```php
12
+
$this->publisher->publish('vendor.product.reindex', $productId);
13
+
14
+
class ReindexConsumer
15
+
{
16
+
public function process(int $productId): void
17
+
{
18
+
//
19
+
}
20
+
}
21
+
```
22
+
23
+
**Symfony** ยท message, handler, routing
24
+
25
+
```php
26
+
final class ReindexProduct
27
+
{
28
+
public function __construct(public readonly int $productId) {}
29
+
}
30
+
31
+
#[AsMessageHandler]
32
+
final class ReindexProductHandler
33
+
{
34
+
public function __invoke(ReindexProduct $message): void
35
+
{
36
+
//
37
+
}
38
+
}
39
+
40
+
$this->bus->dispatch(new ReindexProduct($product->getId()));
41
+
```
42
+
43
+
**Symfony** ยท config/packages/messenger.yaml
44
+
45
+
```yaml
46
+
framework:
47
+
messenger:
48
+
failure_transport: failed
49
+
transports:
50
+
async:
51
+
dsn: '%env(MESSENGER_TRANSPORT_DSN)%' # doctrine://, amqp://, redis://
52
+
retry_strategy: { max_retries: 3, delay: 1000, multiplier: 2 }
53
+
failed: 'doctrine://default?queue_name=failed'
54
+
routing:
55
+
App\Message\ReindexProduct: async
56
+
```
57
+
58
+
- Without a line in `routing` the message is handled synchronously, right on `dispatch()`. Handy in tests and for a gradual migration.
59
+
- Worker: `bin/console messenger:consume async --time-limit=3600 --memory-limit=256M` under supervisor or systemd.
60
+
- Messages that failed after retries sit in `failed`: `messenger:failed:show`, `messenger:failed:retry`.
61
+
- Put ids and scalars into messages, not entities: the message is serialized, and the worker has to re-read the entity.
62
+
63
+
## crontab.xml โ Scheduler
64
+
65
+
**Magento** ยท crontab.xml
66
+
67
+
```xml
68
+
<group id="default">
69
+
<job name="vendor_cleanup_quotes"
70
+
instance="Vendor\Sales\Cron\CleanupQuotes"
71
+
method="execute">
72
+
<schedule>0 3 * * *</schedule>
73
+
</job>
74
+
</group>
75
+
```
76
+
77
+
**Symfony** ยท symfony/scheduler
78
+
79
+
```php
80
+
use Symfony\Component\Scheduler\Attribute\AsCronTask;
81
+
82
+
#[AsCronTask('0 3 * * *')]
83
+
final class CleanupExpiredQuotes
84
+
{
85
+
public function __invoke(): void
86
+
{
87
+
//
88
+
}
89
+
}
90
+
91
+
# the schedule is run by a Messenger worker:
92
+
# bin/console messenger:consume scheduler_default
93
+
```
94
+
95
+
An alternative without Scheduler is a regular console command in the system crontab. For tasks that must not run in parallel on several servers, add the Lock component.