Skip to content

Commit 2adb322

Browse files
authored
Feat: Multiple next tick callbacks (#29)
1 parent eb16e95 commit 2adb322

File tree

3 files changed

+30
-16
lines changed

3 files changed

+30
-16
lines changed

Diff for: src/EtlExecutor.php

+3-4
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,10 @@ public function process(mixed $source = null, mixed $destination = null, array $
110110

111111
private function consumeNextTick(EtlState $state): void
112112
{
113-
if (null === $state->nextTickCallback) {
114-
return;
113+
foreach ($state->nextTickCallbacks as $callback) {
114+
($callback)($state);
115+
$state->nextTickCallbacks->detach($callback);
115116
}
116-
117-
($state->nextTickCallback)($state);
118117
}
119118

120119
/**

Diff for: src/EtlState.php

+7-12
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@
99
use BenTools\ETL\Internal\ClonableTrait;
1010
use Closure;
1111
use DateTimeImmutable;
12+
use SplObjectStorage;
1213

1314
final class EtlState
1415
{
1516
use ClonableTrait;
1617

1718
/**
1819
* @internal
20+
*
21+
* @var SplObjectStorage<Closure, Closure>
1922
*/
20-
public ?Closure $nextTickCallback = null;
23+
public SplObjectStorage $nextTickCallbacks;
2124

2225
private int $nbLoadedItemsSinceLastFlush = 0;
2326
private bool $earlyFlush = false;
@@ -39,20 +42,12 @@ public function __construct(
3942
public readonly ?DateTimeImmutable $endedAt = null,
4043
public readonly mixed $output = null,
4144
) {
45+
$this->nextTickCallbacks ??= new SplObjectStorage();
4246
}
4347

44-
public function nextTick(?callable $callback): void
48+
public function nextTick(callable $callback): void
4549
{
46-
if (null === $callback) {
47-
$this->nextTickCallback = null;
48-
49-
return;
50-
}
51-
52-
$this->nextTickCallback = static function (EtlState $state) use ($callback) {
53-
$callback($state);
54-
$state->nextTick(null);
55-
};
50+
$this->nextTickCallbacks->attach(static fn (EtlState $state) => $callback($state));
5651
}
5752

5853
/**

Diff for: tests/Behavior/NextTickTest.php

+20
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44

55
namespace BenTools\ETL\Tests\Behavior;
66

7+
use ArrayObject;
78
use BenTools\ETL\EtlConfiguration;
89
use BenTools\ETL\EtlExecutor;
910
use BenTools\ETL\EtlState;
1011
use BenTools\ETL\EventDispatcher\Event\ExtractEvent;
12+
use BenTools\ETL\EventDispatcher\Event\LoadEvent;
1113
use BenTools\ETL\Tests\InMemoryLoader;
1214

1315
use function expect;
@@ -35,3 +37,21 @@
3537
->and($report->output[0])->toBe(['banana', 'apple'])
3638
->and($report->output[1])->toBe(['strawberry', 'raspberry', 'peach']);
3739
});
40+
41+
it('can trigger several callbacks, which are called only once', function () {
42+
// Given
43+
$bucket = new ArrayObject();
44+
$etl = (new EtlExecutor())
45+
->onLoad(function (LoadEvent $event) use ($bucket) {
46+
if ('apple' === $event->item) {
47+
$event->state->nextTick(fn (EtlState $state) => $bucket->append('apple'));
48+
$event->state->nextTick(fn (EtlState $state) => $bucket->append('APPLE'));
49+
}
50+
});
51+
52+
// When
53+
$report = $etl->process(['banana', 'apple', 'strawberry', 'raspberry', 'peach']);
54+
55+
// Then
56+
expect([...$bucket])->toBe(['apple', 'APPLE']);
57+
});

0 commit comments

Comments
 (0)