Skip to content
This repository was archived by the owner on Jun 2, 2023. It is now read-only.

Commit 5773ddd

Browse files
authored
Merge pull request #10 from lamoda/feature/SCENTRE-5889_extend_retry_sending_time
SCENTRE-5889 Add availability of select special strategy for queue
2 parents e02e4dd + 1edeba0 commit 5773ddd

15 files changed

+390
-47
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
/vendor/
22
/composer.lock
3-
/.php_cs.cache
3+
/.php_cs.cache

README.md

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Symfony bundle for convenient work with queues. Currently it supports RabbitMQ.
3737
max_attempts: 5
3838
batch_size_per_requeue: 5
3939
batch_size_per_republish: 5
40-
## optional
40+
## optional (will use for default delay Geometric Progression Strategy)
4141
strategy_delay_geometric_progression_start_interval_sec: 60
4242
strategy_delay_geometric_progression_multiplier: 2
4343
```
@@ -199,6 +199,47 @@ Symfony bundle for convenient work with queues. Currently it supports RabbitMQ.
199199
- { name: queue.handler, handle: App\Job\SendNotificationJob }
200200
```
201201

202+
1. Configure delay strategy parameters (optional)
203+
204+
```yaml
205+
lamoda_queue:
206+
...
207+
queues:
208+
queue_one: 'delay_arithmetic_progression'
209+
queue_two: 'delay_special_geometric_progression'
210+
211+
# Settings of special behaviors for Delay strategies (optional)
212+
services:
213+
lamoda_queue.strategy.delay.arithmetic_progression:
214+
class: Lamoda\QueueBundle\Strategy\Delay\ArithmeticProgressionStrategy
215+
tags:
216+
- { name: 'lamoda_queue_strategy', key: 'delay_arithmetic_progression' }
217+
arguments:
218+
- 60 # start_interval_sec parameter
219+
- 1700 # multiplier parameter
220+
221+
lamoda_queue.strategy.delay.geometric_progression:
222+
class: Lamoda\QueueBundle\Strategy\Delay\GeometricProgressionStrategy
223+
tags:
224+
- { name: 'lamoda_queue_strategy', key: 'delay_special_geometric_progression' }
225+
arguments:
226+
- 70 # start_interval_sec parameter
227+
- 4 # multiplier parameter
228+
229+
```
230+
In this block, you can config special delay behaviors for each queue. For this, you have to register new services that
231+
use one of several base strategies (ArithmeticProgressionStrategy, GeometricProgressionStrategy) or yours (for this you
232+
have to make Service Class that implements DelayStrategyInterface).
233+
234+
Each strategy service has to have a tag with name `lamoda_queue_strategy` and unique `key`.
235+
After this, you can use these `keys` for matching with queues in `lamoda_queue.queues` section.
236+
237+
By default, use GeometricProgressionStrategy with params (their you can customize in `lamoda_queue` config section):
238+
```
239+
strategy_delay_geometric_progression_start_interval_sec: 60
240+
strategy_delay_geometric_progression_multiplier: 2
241+
```
242+
202243
6. Add queue name in "codeception.yml" at `modules.config.AMQP.queues`
203244

204245
7. Execute `./bin/console queue:init` command

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"symfony/console": "^4.2 || ^5.0",
1818
"symfony/dependency-injection": "^4.2 || ^5.0",
1919
"symfony/event-dispatcher": "^4.3 || ^5.0",
20+
"symfony/framework-bundle": "^4.3",
2021
"symfony/monolog-bundle": "^3.3"
2122
},
2223
"require-dev": {

src/DependencyInjection/Configuration.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Lamoda\QueueBundle\DependencyInjection;
66

7+
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
78
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
89
use Symfony\Component\Config\Definition\ConfigurationInterface;
910

@@ -40,6 +41,22 @@ public function getConfigTreeBuilder(): TreeBuilder
4041
->end()
4142
->end();
4243

44+
$this->addQueues($rootNode);
45+
4346
return $treeBuilder;
4447
}
48+
49+
50+
protected function addQueues(ArrayNodeDefinition $node)
51+
{
52+
$node
53+
->children()
54+
->arrayNode('queues')
55+
->canBeUnset()
56+
->useAttributeAsKey('key')
57+
->treatNullLike(array())
58+
->prototype('scalar')->end()
59+
->end()
60+
;
61+
}
4562
}

src/DependencyInjection/LamodaQueueExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@ public function load(array $configs, ContainerBuilder $container): void
3333
$container->setParameter('lamoda_queue.strategy_delay_geometric_progression_start_interval_sec', $config['strategy_delay_geometric_progression_start_interval_sec']);
3434
$container->setParameter('lamoda_queue.strategy_delay_geometric_progression_multiplier', $config['strategy_delay_geometric_progression_multiplier']);
3535
$container->setParameter('lamoda_queue.command_unexpected_end_script_timeout', $config['command_unexpected_end_script_timeout']);
36+
$container->setParameter('lamoda_queue.queues_configuration', $config['queues']);
3637
}
3738
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Lamoda\QueueBundle\Exception;
6+
7+
class UnknownStrategyKeyException extends \UnexpectedValueException
8+
{
9+
}

src/Resources/config/services.yml

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,6 @@ services:
6565
- '@Lamoda\QueueBundle\Factory\EntityFactory'
6666
- '@event_dispatcher'
6767
- '%lamoda_queue.max_attempts%'
68-
Lamoda\QueueBundle\Service\DelayService:
69-
arguments:
70-
- '@Lamoda\QueueBundle\Strategy\Delay\DelayStrategyInterface'
71-
Lamoda\QueueBundle\Strategy\Delay\GeometricProgressionStrategy:
72-
arguments:
73-
- '%lamoda_queue.strategy_delay_geometric_progression_start_interval_sec%'
74-
- '%lamoda_queue.strategy_delay_geometric_progression_multiplier%'
7568
Lamoda\QueueBundle\Command\QueueRepublishCommand:
7669
public: true
7770
arguments:
@@ -98,3 +91,17 @@ services:
9891
public: true
9992
tags:
10093
- { name: console.command }
94+
Lamoda\QueueBundle\Service\DelayService:
95+
arguments:
96+
- '@Lamoda\QueueBundle\Service\DelayStrategyResolver'
97+
- '@Psr\Log\LoggerInterface'
98+
Lamoda\QueueBundle\Strategy\Delay\GeometricProgressionStrategy:
99+
arguments:
100+
- '%lamoda_queue.strategy_delay_geometric_progression_start_interval_sec%'
101+
- '%lamoda_queue.strategy_delay_geometric_progression_multiplier%'
102+
tags:
103+
- { name: 'lamoda_queue_strategy', key: !php/const Lamoda\QueueBundle\Service\DelayStrategyResolver::DEFAULT_STRATEGY }
104+
Lamoda\QueueBundle\Service\DelayStrategyResolver:
105+
arguments:
106+
- !tagged { tag: 'lamoda_queue_strategy', index_by: 'key' }
107+
- '%lamoda_queue.queues_configuration%'

src/Service/DelayService.php

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,43 @@
66

77
use DateTime;
88
use Lamoda\QueueBundle\Entity\QueueEntityInterface;
9-
use Lamoda\QueueBundle\Strategy\Delay\DelayStrategyInterface;
9+
use Lamoda\QueueBundle\Exception\UnknownStrategyKeyException;
10+
use Psr\Log\LoggerInterface;
1011

1112
class DelayService
1213
{
1314
/**
14-
* @var DelayStrategyInterface
15+
* @var DelayStrategyResolver
1516
*/
16-
protected $strategy;
17+
protected $strategyService;
1718

18-
public function __construct(DelayStrategyInterface $strategy)
19+
/**
20+
* @var LoggerInterface
21+
*/
22+
private $logger;
23+
24+
public function __construct(DelayStrategyResolver $strategyService, LoggerInterface $logger)
1925
{
20-
$this->strategy = $strategy;
26+
$this->strategyService = $strategyService;
27+
$this->logger = $logger;
2128
}
2229

2330
public function delayQueue(QueueEntityInterface $queue): QueueEntityInterface
2431
{
25-
$iteration = $queue->getAttempts() ?? 1;
26-
$newDelayInterval = $this->strategy->generateInterval($iteration);
27-
$delayUntil = $this->getStartDateTime()->add($newDelayInterval);
32+
try {
33+
$strategy = $this->strategyService->getStrategy($queue->getName());
34+
} catch (UnknownStrategyKeyException $exception) {
35+
$this->logger->warning(
36+
$exception->getMessage(), [
37+
'queue_name' => $queue->getName(),
38+
]
39+
);
40+
$strategy = $this->strategyService->getDefaultStrategy();
41+
}
42+
43+
$iteration = $queue->getAttempts() ?? 1;
44+
$newDelayInterval = $strategy->generateInterval($iteration);
45+
$delayUntil = $this->getStartDateTime()->add($newDelayInterval);
2846

2947
$queue->setWaiting($delayUntil);
3048

src/Service/DelayStrategyResolver.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Lamoda\QueueBundle\Service;
5+
6+
use Lamoda\QueueBundle\Exception\UnknownStrategyKeyException;
7+
use Lamoda\QueueBundle\Strategy\Delay\DelayStrategyInterface;
8+
9+
class DelayStrategyResolver
10+
{
11+
public const DEFAULT_STRATEGY = 'default_delay_strategy';
12+
13+
/**
14+
* @var array
15+
*/
16+
protected $handlers;
17+
18+
/**
19+
* @var array
20+
*/
21+
protected $queuesConfiguration;
22+
23+
public function __construct(iterable $handlers, array $queuesConfiguration = [])
24+
{
25+
$this->handlers = iterator_to_array($handlers);
26+
$this->queuesConfiguration = $queuesConfiguration;
27+
}
28+
29+
/**
30+
* @param string $queueName
31+
*
32+
* @return DelayStrategyInterface
33+
* @throws UnknownStrategyKeyException
34+
*/
35+
public function getStrategy(string $queueName): DelayStrategyInterface
36+
{
37+
$strategyKey = $this->queuesConfiguration[$queueName] ?? self::DEFAULT_STRATEGY;
38+
39+
if (isset($this->handlers[$strategyKey])) {
40+
return $this->handlers[$strategyKey];
41+
}
42+
43+
throw new UnknownStrategyKeyException(sprintf('Delay strategy with key: %s doesn\'t exist', $strategyKey));
44+
}
45+
46+
public function getDefaultStrategy(): DelayStrategyInterface
47+
{
48+
return $this->handlers[self::DEFAULT_STRATEGY];
49+
}
50+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Lamoda\QueueBundle\Strategy\Delay;
6+
7+
use DateInterval;
8+
9+
class ArithmeticProgressionStrategy implements DelayStrategyInterface
10+
{
11+
/** @var int */
12+
private $startInterval;
13+
14+
/** @var float */
15+
private $multiplier;
16+
17+
public function __construct(int $startIntervalSec, float $multiplier)
18+
{
19+
$this->startInterval = $startIntervalSec;
20+
$this->multiplier = $multiplier;
21+
}
22+
23+
public function generateInterval(int $iteration): DateInterval
24+
{
25+
$newIntervalSec = (int) ceil($this->startInterval + ($this->multiplier * ($iteration - 1)));
26+
27+
return new DateInterval('PT' . $newIntervalSec . 'S');
28+
}
29+
}

0 commit comments

Comments
 (0)