docs(articles): From Magento to Symfony, a requalification guide grouped into sections
uk/articles/magento-to-symfony/infrastructure/async.md
новий файл +95
−0
1
+
# Черги та cron
2
+
3
+
**Magento** · чотири XML і 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 — ще три файли -->
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** · повідомлення, обробник, маршрут
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
+
- Без рядка в `routing` повідомлення обробиться синхронно, одразу при `dispatch()`. Зручно в тестах і для поступового переходу.
59
+
- Воркер: `bin/console messenger:consume async --time-limit=3600 --memory-limit=256M` під supervisor або systemd.
60
+
- Провалені після ретраїв повідомлення лежать у `failed`: `messenger:failed:show`, `messenger:failed:retry`.
61
+
- У повідомлення кладуть id і скаляри, а не сутності: повідомлення серіалізується, а сутність у воркері треба перечитати.
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
+
# запуск розкладу — це воркер Messenger:
92
+
# bin/console messenger:consume scheduler_default
93
+
```
94
+
95
+
Альтернатива без Scheduler — звичайна консольна команда в системному crontab. Для задач, які не можна запускати паралельно на кількох серверах, додайте компонент Lock.