-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCursor.php
More file actions
64 lines (53 loc) · 1.93 KB
/
Copy pathCursor.php
File metadata and controls
64 lines (53 loc) · 1.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?php
declare(strict_types=1);
namespace Utopia\Feed;
use Utopia\Feed\Exception\Invalid;
abstract class Cursor
{
/**
* @throws Exception When the store cannot be read.
*/
abstract public function load(string $feed, string $consumer): ?string;
/**
* @throws Exception When the store cannot be written.
*/
abstract public function save(string $feed, string $consumer, string $eventId): void;
/**
* @throws Exception When the store cannot be written.
*/
abstract public function reset(string $feed, string $consumer): void;
/**
* Save $eventId only if the stored position is still $expected — what the
* caller's run started from, or null for none. A refusal means another
* instance moved the position, and that newer decision stands.
*
* Equality is all it takes, so it works on ids with no order (a remote
* feed's UUIDs). The check is read-compare-write, not atomic: it narrows
* the window for a lost update from a whole run to one round trip, and
* what slips through costs a bounded replay, which at-least-once delivery
* absorbs anyway.
*
* @throws Exception When the store cannot be read or written.
*/
public function advance(string $feed, string $consumer, string $eventId, ?string $expected): bool
{
if ($this->load($feed, $consumer) !== $expected) {
return false;
}
$this->save($feed, $consumer, $eventId);
return true;
}
/**
* The gate every cursor operation goes through, so no adapter builds a key
* of its own and skips the check.
*
* @throws Invalid When either name is empty.
*/
protected function key(string $feed, string $consumer): string
{
if ($feed === '' || $consumer === '') {
throw new Invalid('Cursor requires a feed and a consumer name');
}
return Key::cursor($feed, $consumer);
}
}