Skip to content

Commit 92fa710

Browse files
committed
allow modifying the schedule at runtime at recalculate heap when needed
1 parent 11adee9 commit 92fa710

File tree

3 files changed

+110
-3
lines changed

3 files changed

+110
-3
lines changed

src/Symfony/Component/Scheduler/Generator/MessageGenerator.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
final class MessageGenerator implements MessageGeneratorInterface
2121
{
22-
private Schedule $schedule;
22+
private ?Schedule $schedule = null;
2323
private TriggerHeap $triggerHeap;
2424
private ?\DateTimeImmutable $waitUntil;
2525

@@ -36,6 +36,12 @@ public function getMessages(): \Generator
3636
{
3737
$checkpoint = $this->checkpoint();
3838

39+
if ($this->schedule?->restart()) {
40+
unset($this->triggerHeap);
41+
$this->waitUntil = new \DateTimeImmutable('@0');
42+
$this->schedule->restart(false);
43+
}
44+
3945
if (!$this->waitUntil
4046
|| $this->waitUntil > ($now = $this->clock->now())
4147
|| !$checkpoint->acquire($now)

src/Symfony/Component/Scheduler/Schedule.php

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,49 @@ final class Schedule implements ScheduleProviderInterface
2222
private ?LockInterface $lock = null;
2323
private ?CacheInterface $state = null;
2424

25+
private bool $restart = false;
26+
27+
public static function with(RecurringMessage $message, RecurringMessage ...$messages): static
28+
{
29+
return static::doAdd(new self(), $message, ...$messages);
30+
}
31+
2532
/**
2633
* @return $this
2734
*/
2835
public function add(RecurringMessage $message, RecurringMessage ...$messages): static
36+
{
37+
$this->restart(true);
38+
39+
return static::doAdd($this, $message, ...$messages);
40+
}
41+
42+
private static function doAdd(self $schedule, RecurringMessage $message, RecurringMessage ...$messages): static
2943
{
3044
foreach ([$message, ...$messages] as $m) {
31-
if (isset($this->messages[$m->getId()])) {
45+
if (isset($schedule->messages[$m->getId()])) {
3246
throw new LogicException('Duplicated schedule message.');
3347
}
3448

35-
$this->messages[$m->getId()] = $m;
49+
$schedule->messages[$m->getId()] = $m;
3650
}
3751

52+
return $schedule;
53+
}
54+
55+
public function remove(RecurringMessage $message): static
56+
{
57+
unset($this->messages[$message->getId()]);
58+
$this->restart(true);
59+
60+
return $this;
61+
}
62+
63+
public function clear(): static
64+
{
65+
$this->messages = [];
66+
$this->restart(true);
67+
3868
return $this;
3969
}
4070

@@ -83,4 +113,9 @@ public function getSchedule(): static
83113
{
84114
return $this;
85115
}
116+
117+
public function restart(bool $restart = null): bool
118+
{
119+
return $this->restart = $restart ?? $this->restart;
120+
}
86121
}

src/Symfony/Component/Scheduler/Tests/Generator/MessageGeneratorTest.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,72 @@ public function getSchedule(): Schedule
9595
}
9696
}
9797

98+
public function testGetMessagesFromScheduleProviderWithRestart()
99+
{
100+
$first = (object) ['id' => 'first'];
101+
$startTime = '22:12:00';
102+
$runs = [
103+
'22:12:00' => [],
104+
'22:12:01' => [],
105+
'22:13:00' => [$first],
106+
'22:13:01' => [],
107+
];
108+
$schedule = [[$first, '22:13:00', '22:14:00']];
109+
110+
// for referencing
111+
$now = self::makeDateTime($startTime);
112+
113+
$clock = $this->createMock(ClockInterface::class);
114+
$clock->method('now')->willReturnReference($now);
115+
116+
foreach ($schedule as $i => $s) {
117+
if (\is_array($s)) {
118+
$schedule[$i] = $this->createMessage(...$s);
119+
}
120+
}
121+
122+
$scheduleProvider = new class($schedule) implements ScheduleProviderInterface {
123+
private Schedule $schedule;
124+
125+
public function __construct(array $schedule)
126+
{
127+
$this->schedule = Schedule::with(...$schedule);
128+
$this->schedule->stateful(new ArrayAdapter());
129+
}
130+
131+
public function getSchedule(): Schedule
132+
{
133+
return $this->schedule;
134+
}
135+
136+
public function add(RecurringMessage $message): self
137+
{
138+
$this->schedule->add($message);
139+
140+
return $this;
141+
}
142+
};
143+
144+
$scheduler = new MessageGenerator($scheduleProvider, 'dummy', $clock);
145+
146+
// Warmup. The first run always returns nothing.
147+
$this->assertSame([], iterator_to_array($scheduler->getMessages(), false));
148+
149+
$toAdd = (object) ['id' => 'added-after-start'];
150+
151+
foreach ($runs as $time => $expected) {
152+
$now = self::makeDateTime($time);
153+
$this->assertSame($expected, iterator_to_array($scheduler->getMessages(), false));
154+
}
155+
156+
$scheduleProvider->add($this->createMessage($toAdd, '22:13:10', '22:13:11'));
157+
158+
$this->assertSame([], iterator_to_array($scheduler->getMessages(), false));
159+
160+
$now = self::makeDateTime('22:13:10');
161+
$this->assertSame([$toAdd], iterator_to_array($scheduler->getMessages(), false));
162+
}
163+
98164
public function testYieldedContext()
99165
{
100166
// for referencing

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy