Skip to content

Commit 18e4742

Browse files
committed
convert entity and orchestration ids to records
Signed-off-by: Robert Landers <landers.robert@gmail.com>
1 parent d6528ed commit 18e4742

24 files changed

Lines changed: 307 additions & 164 deletions

.idea/durable-php.iml

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/php.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/init/template/tests/integrationTest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,20 @@
66
use Bottledcode\DurablePhp\State\Serializer;
77
use {{.Name}}\Entities\CountInterface;
88
use {{.Name}}\Orchestrations\Password;
9+
use function Bottledcode\DurablePhp\EntityId;
10+
use function Bottledcode\DurablePhp\OrchestrationInstance;
911

1012
require_once __DIR__ . '/../vendor/autoload.php';
1113

1214
$client = DurableClient::get();
1315

1416

15-
$entity = new EntityId(CountInterface::class, random_int(0, 10000));
17+
$entity = EntityId(CountInterface::class, random_int(0, 10000));
1618

1719
echo "Signaling an entity, which will start an orchestration, which we will wait for completion\n";
1820
$start = microtime(true);
1921
$client->signal($entity, fn(CountInterface $state) => $state->countTo(100));
20-
$client->waitForCompletion(new OrchestrationInstance(\{{.Name}}\Orchestrations\Counter::class, $entity->id));
22+
$client->waitForCompletion(OrchestrationInstance(\{{.Name}}\Orchestrations\Counter::class, $entity->id));
2123
$time = number_format(microtime(true) - $start, 2);
2224
echo "Cool! That took $time seconds\n";
2325
echo "Here's the state:\n" . json_encode($client->getEntitySnapshot($entity, CountInterface::class), JSON_PRETTY_PRINT) . "\n";

composer.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
"autoload": {
99
"psr-4": {
1010
"Bottledcode\\DurablePhp\\": "src/"
11-
}
11+
},
12+
"files": [
13+
"src/functions.php"
14+
]
1215
},
1316
"autoload-dev": {
1417
"psr-4": {
@@ -33,13 +36,13 @@
3336
"amphp/parallel": "^2.2.9",
3437
"crell/serde": "^1.2.0",
3538
"nesbot/carbon": ">2.0",
39+
"nikic/php-parser": "^5.1",
3640
"php": ">=8.4",
3741
"php-di/php-di": "^7.0.7",
3842
"ramsey/uuid": "^4.7.6",
3943
"webonyx/graphql-php": "^15.12.5",
40-
"withinboredom/time": "^6.0.0",
41-
"nikic/php-parser": "^5.1",
42-
"withinboredom/record": "v0.1.0"
44+
"withinboredom/records": "v0.1.2",
45+
"withinboredom/time": "^6.0.0"
4346
},
4447
"require-dev": {
4548
"laravel/pint": "^1.17.2",

docs/orchestrations.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ Here's an example showing a lock:
132132

133133
```php
134134
function orch(\Bottledcode\DurablePhp\OrchestrationContext $context): void {
135-
$entityId = new \Bottledcode\DurablePhp\State\EntityId('myEntity', 'id');
135+
$entityId = \Bottledcode\DurablePhp\EntityId('myEntity', 'id');
136136
$lock = $context->lockEntity($entityId);
137137
// from here-on, you have exclusive access to the entity
138138
$context->entityOp($entityId, fn($entity) => $entity->add(5));

src/EntityContext.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
use Bottledcode\DurablePhp\State\EntityHistory;
3737
use Bottledcode\DurablePhp\State\EntityId;
3838
use Bottledcode\DurablePhp\State\Ids\StateId;
39-
use Bottledcode\DurablePhp\State\OrchestrationInstance;
4039
use Closure;
4140
use Crell\Serde\Attributes\ClassSettings;
4241
use DateTimeImmutable;
@@ -132,7 +131,7 @@ public function startNewOrchestration(string $orchestration, array $input = [],
132131
$id = Uuid::uuid7()->toString();
133132
}
134133

135-
$instance = StateId::fromInstance(new OrchestrationInstance($orchestration, $id));
134+
$instance = StateId::fromInstance(OrchestrationInstance($orchestration, $id));
136135
$this->eventDispatcher->fire(
137136
WithOrchestration::forInstance(
138137
$instance,

src/Gateway/Graph/index.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
/*
34
* Copyright ©2024 Robert Landers
45
*
@@ -25,15 +26,16 @@
2526

2627
use Bottledcode\DurablePhp\DurableClient;
2728
use Bottledcode\DurablePhp\SerializedArray;
28-
use Bottledcode\DurablePhp\State\EntityId;
29-
use Bottledcode\DurablePhp\State\OrchestrationInstance;
3029
use Bottledcode\DurablePhp\State\Serializer;
3130
use GraphQL\Error\DebugFlag;
3231
use GraphQL\Language\AST\TypeDefinitionNode;
3332
use GraphQL\Server\ServerConfig;
3433
use GraphQL\Server\StandardServer;
3534
use GraphQL\Utils\BuildSchema;
3635

36+
use function Bottledcode\DurablePhp\EntityId;
37+
use function Bottledcode\DurablePhp\OrchestrationInstance;
38+
3739
require_once __DIR__ . '/../../Glue/autoload.php';
3840

3941
header('Content-Type: text/plain');
@@ -52,7 +54,7 @@
5254

5355
function getOrchestrationStatus(array $args, DurableClient $context): array
5456
{
55-
$id = new OrchestrationInstance($args['id']['instance'], $args['id']['execution']);
57+
$id = OrchestrationInstance($args['id']['instance'], $args['id']['execution']);
5658
if ($args['waitForCompletion'] ?? false) {
5759
$context->waitForCompletion($id);
5860
}
@@ -65,7 +67,7 @@ function getOrchestrationStatus(array $args, DurableClient $context): array
6567

6668
function getEntitySnapshot(array $args, DurableClient $context): array
6769
{
68-
$id = new EntityId($args['id']['name'], $args['id']['id']);
70+
$id = EntityId($args['id']['name'], $args['id']['id']);
6971

7072
return Serializer::serialize($context->getEntitySnapshot($id));
7173
}
@@ -90,7 +92,7 @@ function startOrchestration(array $args, DurableClient $context): array
9092

9193
function raiseEvent(array $args, DurableClient $context): array
9294
{
93-
$id = new OrchestrationInstance($args['id']['instance'], $args['id']['execution']);
95+
$id = OrchestrationInstance($args['id']['instance'], $args['id']['execution']);
9496
$arguments = array_map(
9597
static fn($x, $i) => ['key' => $i, ...$x],
9698
$args['arguments'],
@@ -104,7 +106,7 @@ function raiseEvent(array $args, DurableClient $context): array
104106

105107
function signal(array $args, DurableClient $context): array
106108
{
107-
$id = new EntityId($args['id']['name'], $args['id']['id']);
109+
$id = EntityId($args['id']['name'], $args['id']['id']);
108110
$signal = $args['signal'];
109111
unset($args['id'], $args['signal']);
110112

src/Glue/glue.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
use Bottledcode\DurablePhp\State\EntityHistory;
4141
use Bottledcode\DurablePhp\State\Ids\StateId;
4242
use Bottledcode\DurablePhp\State\OrchestrationHistory;
43-
use Bottledcode\DurablePhp\State\OrchestrationInstance;
4443
use Bottledcode\DurablePhp\State\Serializer;
4544
use Bottledcode\DurablePhp\State\StateInterface;
4645
use Bottledcode\DurablePhp\Task;
@@ -60,6 +59,8 @@
6059
use ReflectionFunction;
6160
use Withinboredom\Time\Unit;
6261

62+
use function Bottledcode\DurablePhp\OrchestrationInstance;
63+
6364
require_once __DIR__ . '/autoload.php';
6465

6566
class Glue
@@ -193,7 +194,7 @@ private function startOrchestration(): void
193194
{
194195
if (!$this->target->toOrchestrationInstance()->executionId) {
195196
$this->target = StateId::fromInstance(
196-
new OrchestrationInstance(
197+
OrchestrationInstance(
197198
$this->target->toOrchestrationInstance()->instanceId,
198199
Uuid::uuid7()->toString(),
199200
),

src/OrchestrationContext.php

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,13 @@ public function callActivity(string $name, array $args = [], ?RetryOptions $retr
7676
$identity = $this->newGuid();
7777

7878
return $this->createFuture(
79-
fn() => $this->taskController->fire(
80-
AwaitResult::forEvent(
81-
StateId::fromInstance($this->id),
82-
WithActivity::forEvent($identity, ScheduleTask::forName($name, $args)),
79+
fn()
80+
=> $this->taskController->fire(
81+
AwaitResult::forEvent(
82+
StateId::fromInstance($this->id),
83+
WithActivity::forEvent($identity, ScheduleTask::forName($name, $args)),
84+
),
8385
),
84-
),
8586
function (Event $event, string $eventIdentity) use ($identity): array {
8687
if (($event instanceof TaskCompleted || $event instanceof TaskFailed) &&
8788
$eventIdentity === $identity->toString()) {
@@ -114,7 +115,7 @@ private function createFuture(
114115
?string $identity = null,
115116
): DurableFuture {
116117
$identity ??= $this->history->historicalTaskResults->getIdentity();
117-
if (! $this->history->historicalTaskResults->hasSentIdentity($identity)) {
118+
if (!$this->history->historicalTaskResults->hasSentIdentity($identity)) {
118119
$this->durableLogger->debug('Future requested for an unsent identity', [$identity]);
119120
[$eventId] = $onSent();
120121
$deferred = new DeferredFuture();
@@ -141,7 +142,12 @@ public function callActivityInline(Closure $activity): DurableFuture
141142
return $this->createFuture(function () use ($activity, $identity) {
142143
try {
143144
$result = $activity();
144-
$this->taskController->fire(WithOrchestration::forInstance(StateId::fromInstance($this->id), TaskCompleted::forId($identity->toString(), $result)));
145+
$this->taskController->fire(
146+
WithOrchestration::forInstance(
147+
StateId::fromInstance($this->id),
148+
TaskCompleted::forId($identity->toString(), $result),
149+
),
150+
);
145151

146152
return [$identity];
147153
} catch (Throwable $exception) {
@@ -160,7 +166,8 @@ public function callActivityInline(Closure $activity): DurableFuture
160166
return [$identity];
161167
}
162168
}, function (Event $event, string $eventIdentity) use ($identity): array {
163-
if (($event instanceof TaskCompleted || $event instanceof TaskFailed) && $eventIdentity === $identity->toString()) {
169+
if (($event instanceof TaskCompleted || $event instanceof TaskFailed) &&
170+
$eventIdentity === $identity->toString()) {
164171
return [$event, true];
165172
}
166173

@@ -189,7 +196,10 @@ public function continueAsNew(array $args = []): never
189196

190197
$this->history->restartAsNew($args);
191198
$this->taskController->fire(
192-
WithOrchestration::forInstance(StateId::fromInstance($this->id), StartOrchestration::forInstance($this->id)),
199+
WithOrchestration::forInstance(
200+
StateId::fromInstance($this->id),
201+
StartOrchestration::forInstance($this->id),
202+
),
193203
);
194204
throw new Unwind();
195205
}
@@ -204,12 +214,13 @@ public function createTimer(DateTimeImmutable|DateInterval $fireAt): DurableFutu
204214
$identity = sha1($fireAt->format('c'));
205215

206216
return $this->createFuture(
207-
fn() => $this->taskController->fire(
208-
WithOrchestration::forInstance(
209-
StateId::fromInstance($this->id),
210-
WithDelay::forEvent($fireAt, RaiseEvent::forTimer($identity)),
217+
fn()
218+
=> $this->taskController->fire(
219+
WithOrchestration::forInstance(
220+
StateId::fromInstance($this->id),
221+
WithDelay::forEvent($fireAt, RaiseEvent::forTimer($identity)),
222+
),
211223
),
212-
),
213224
function (Event $event) use ($identity): array {
214225
if ($event instanceof RaiseEvent && $event->eventName === $identity) {
215226
return [$event, true];
@@ -300,13 +311,11 @@ public function createInterval(
300311
?int $seconds = null,
301312
?int $microseconds = null,
302313
): DateInterval {
303-
if (
304-
empty(
305-
array_filter(
306-
compact('years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'microseconds'),
307-
)
314+
if (empty(
315+
array_filter(
316+
compact('years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'microseconds'),
308317
)
309-
) {
318+
)) {
310319
throw new LogicException('At least one interval part must be specified');
311320
}
312321

@@ -361,7 +370,7 @@ public function isLockedOwned(EntityId $entityId): bool
361370
public function lockEntity(EntityId ...$entityId): EntityLock
362371
{
363372
$this->durableLogger->debug('Locking entities', ['entityId' => $entityId]);
364-
if (! empty($this->history->locks ?? []) && ! $this->isReplaying()) {
373+
if (!empty($this->history->locks ?? []) && !$this->isReplaying()) {
365374
throw new LogicException('Cannot lock an entity while holding locks');
366375
}
367376

@@ -375,12 +384,11 @@ public function lockEntity(EntityId ...$entityId): EntityLock
375384
WithEntity::forInstance(current($entityId), RaiseEvent::forLockNotification($owner->id)),
376385
);
377386
$identity = $this->newGuid()->toString();
378-
$future =
379-
$this->createFuture(
380-
fn() => $this->taskController->fire(WithLock::onEntity($owner, $event, ...$entityId)),
381-
fn(Event $event, string $eventIdentity) => [$event, $identity === $eventIdentity],
382-
$identity,
383-
);
387+
$future = $this->createFuture(
388+
fn() => $this->taskController->fire(WithLock::onEntity($owner, $event, ...$entityId)),
389+
fn(Event $event, string $eventIdentity) => [$event, $identity === $eventIdentity],
390+
$identity,
391+
);
384392
$this->waitOne($future);
385393

386394
$this->history->locks = $entityId;
@@ -439,17 +447,17 @@ public function waitAll(DurableFuture ...$tasks): array
439447
/**
440448
* @template T
441449
*
442-
* @param class-string<T> $className
450+
* @param class-string<T> $className
443451
* @return T
444452
*/
445453
public function createEntityProxy(string $className, ?EntityId $entityId = null): object
446454
{
447455
if ($entityId === null) {
448-
$entityId = new EntityId($className, $this->newGuid());
456+
$entityId = EntityId($className, $this->newGuid());
449457
}
450458

451459
$class = new ReflectionClass($className);
452-
if (! $class->isInterface()) {
460+
if (!$class->isInterface()) {
453461
throw new LogicException('Only interfaces can be proxied');
454462
}
455463

@@ -569,7 +577,7 @@ public function entityOp(string|EntityId $id, Closure $operation): mixed
569577
}
570578

571579
$name = $type->getName();
572-
if (! interface_exists($name)) {
580+
if (!interface_exists($name)) {
573581
throw new LogicException('Unable to load interface: ' . $name);
574582
}
575583

@@ -588,7 +596,7 @@ public function entityOp(string|EntityId $id, Closure $operation): mixed
588596
throw new LogicException('Did not call an operation');
589597
}
590598

591-
$entityId = $id instanceof EntityId ? $id : new EntityId($name, $id);
599+
$entityId = $id instanceof EntityId ? $id : EntityId($name, $id);
592600

593601
if ($returns) {
594602
return $this->waitOne($this->callEntity($entityId, $operationName, $arguments));

src/RemoteEntityClient.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
/*
34
* Copyright ©2024 Robert Landers
45
*
@@ -47,7 +48,7 @@ public function __construct(
4748
private HttpClient $client = new HttpClient(),
4849
private SpyProxy $spyProxy = new SpyProxy(),
4950
) {
50-
$this->apiHost = rtrim($this->apiHost, '/');
51+
$this->apiHost = mb_rtrim($this->apiHost, '/');
5152
}
5253

5354
#[Override]
@@ -56,7 +57,11 @@ public function cleanEntityStorage(): void {}
5657
#[Override]
5758
public function listEntities(EntityFilter $filter, int $page): Generator
5859
{
59-
$req = new Request($this->apiHost . '/entities/filter/' . $page, 'POST', json_encode($filter, JSON_THROW_ON_ERROR));
60+
$req = new Request(
61+
$this->apiHost . '/entities/filter/' . $page,
62+
'POST',
63+
json_encode($filter, JSON_THROW_ON_ERROR),
64+
);
6065
if ($this->userToken) {
6166
$req->setHeader('Authorization', 'Bearer ' . $this->userToken);
6267
}
@@ -82,7 +87,11 @@ public function signal(EntityId|string $entityId, Closure $signal): void
8287
} catch (Throwable) {
8388
// spies always throw
8489
}
85-
$this->signalEntity(is_string($entityId) ? new EntityId($interfaceName, $entityId) : $entityId, $operationName, $arguments);
90+
$this->signalEntity(
91+
is_string($entityId) ? EntityId($interfaceName, $entityId) : $entityId,
92+
$operationName,
93+
$arguments,
94+
);
8695
}
8796

8897
#[Override]

0 commit comments

Comments
 (0)