Skip to content

Commit 9e0ec36

Browse files
committed
feat: introduce WorkflowVersioningBehavior attribute and enhance workflow versioning support
1 parent 3733d54 commit 9e0ec36

File tree

5 files changed

+76
-20
lines changed

5 files changed

+76
-20
lines changed

src/Internal/Declaration/Graph/ClassNode.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public function count(): int
5858
* Get a method with all the declared classes.
5959
*
6060
* @param non-empty-string $name
61-
* @return \Traversable<ClassNode, \ReflectionMethod>
61+
* @return \Traversable<int, \Traversable<class-string, \ReflectionMethod>>
6262
* @throws \ReflectionException
6363
*/
6464
public function getMethods(string $name, bool $reverse = true): \Traversable
@@ -190,6 +190,7 @@ private function getInheritance(): array
190190

191191
/**
192192
* @param iterable<ClassNode> $classes
193+
* @return list<array{class-string, \ReflectionMethod}>
193194
* @throws \ReflectionException
194195
*/
195196
private function boxMethods(iterable $classes, string $name): array
@@ -205,6 +206,10 @@ private function boxMethods(iterable $classes, string $name): array
205206
return $result;
206207
}
207208

209+
/**
210+
* @param array<array{class-string, \ReflectionMethod}> $boxed
211+
* @return \Traversable<class-string, \ReflectionMethod>
212+
*/
208213
private function unboxMethods(array $boxed): \Traversable
209214
{
210215
$unpack = static function () use ($boxed) {

src/Internal/Declaration/Prototype/WorkflowPrototype.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Temporal\Common\CronSchedule;
1515
use Temporal\Common\MethodRetry;
1616
use Temporal\Internal\Declaration\EntityNameValidator;
17+
use Temporal\Worker\Versioning\VersioningBehavior;
1718
use Temporal\Workflow\ReturnType;
1819
use Temporal\Workflow\WorkflowInit;
1920

@@ -43,12 +44,14 @@ final class WorkflowPrototype extends Prototype
4344
private ?MethodRetry $methodRetry = null;
4445
private ?ReturnType $returnType = null;
4546
private bool $hasInitializer = false;
47+
private VersioningBehavior $versioningBehavior;
4648

4749
public function __construct(
4850
string $name,
4951
?\ReflectionMethod $handler,
5052
\ReflectionClass $class,
5153
) {
54+
$this->versioningBehavior = VersioningBehavior::Unspecified;
5255
EntityNameValidator::validateWorkflow($name);
5356
parent::__construct($name, $handler, $class);
5457
}
@@ -96,6 +99,11 @@ public function setReturnType(?ReturnType $attribute): void
9699
$this->returnType = $attribute;
97100
}
98101

102+
public function setVersioningBehavior(VersioningBehavior $behavior): void
103+
{
104+
$this->versioningBehavior = $behavior;
105+
}
106+
99107
public function addQueryHandler(QueryDefinition $definition): void
100108
{
101109
EntityNameValidator::validateQueryMethod($definition->name);
@@ -156,4 +164,9 @@ public function getValidateUpdateHandlers(): array
156164
{
157165
return $this->updateValidators;
158166
}
167+
168+
public function getVersioningBehavior(): VersioningBehavior
169+
{
170+
return $this->versioningBehavior;
171+
}
159172
}

src/Internal/Declaration/Reader/WorkflowReader.php

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use Temporal\Workflow\WorkflowInit;
2828
use Temporal\Workflow\WorkflowInterface;
2929
use Temporal\Workflow\WorkflowMethod;
30+
use Temporal\Workflow\WorkflowVersioningBehavior;
3031

3132
/**
3233
* @template-extends Reader<WorkflowPrototype>
@@ -292,14 +293,16 @@ private function getAttributedMethod(ClassNode $graph, \ReflectionMethod $handle
292293
}
293294

294295
/**
296+
* Walk through the method hierarchy and build the prototype for the workflow method.
297+
*
295298
* @throws \ReflectionException
296299
*/
297300
private function getPrototype(ClassNode $graph, \ReflectionMethod $handler): ?WorkflowPrototype
298301
{
299-
$cronSchedule = $previousRetry = $prototype = $returnType = null;
302+
$cronSchedule = $previousRetry = $prototype = $returnType = $versionBehavior = null;
300303

304+
/** @var \Traversable<class-string, \ReflectionMethod> $group */
301305
foreach ($graph->getMethods($handler->getName()) as $group) {
302-
//
303306
$contextualRetry = $previousRetry;
304307

305308
foreach ($group as $method) {
@@ -326,6 +329,11 @@ private function getPrototype(ClassNode $graph, \ReflectionMethod $handler): ?Wo
326329
?? $returnType
327330
;
328331

332+
// Version Behavior
333+
$versionBehavior = $this->reader->firstFunctionMetadata($method, WorkflowVersioningBehavior::class)
334+
?? $versionBehavior
335+
;
336+
329337
//
330338
// In the future, workflow methods are available only in
331339
// those classes that contain the attribute:
@@ -347,27 +355,18 @@ private function getPrototype(ClassNode $graph, \ReflectionMethod $handler): ?Wo
347355
}
348356
}
349357

350-
// In case
358+
// Skip if no interface found
351359
if ($interface === null) {
352360
continue;
353361
}
354362

355363
\assert($context !== null);
356-
if ($prototype === null) {
357-
$prototype = $this->findProto($handler, $method, $context, $graph->getReflection());
358-
}
359-
360-
if ($prototype !== null && $retry !== null) {
361-
$prototype->setMethodRetry($retry);
362-
}
363-
364-
if ($prototype !== null && $cronSchedule !== null) {
365-
$prototype->setCronSchedule($cronSchedule);
366-
}
364+
$prototype ??= $this->findProto($handler, $method, $context, $graph->getReflection());
367365

368-
if ($prototype !== null && $returnType !== null) {
369-
$prototype->setReturnType($returnType);
370-
}
366+
$retry === null or $prototype?->setMethodRetry($retry);
367+
$cronSchedule === null or $prototype?->setCronSchedule($cronSchedule);
368+
$returnType === null or $prototype?->setReturnType($returnType);
369+
$versionBehavior === null or $prototype?->setVersioningBehavior($versionBehavior->value);
371370
}
372371

373372
$previousRetry = $contextualRetry;

src/Internal/Transport/Router/GetWorkerInfo.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ public function handle(ServerRequestInterface $request, array $headers, Deferred
4444
private function workerToArray(WorkerInterface $worker): array
4545
{
4646
$workflowMap = static fn(WorkflowPrototype $workflow): array => [
47-
'Name' => $workflow->getID(),
47+
'Name' => $workflow->getID(),
4848
'Queries' => \array_keys($workflow->getQueryHandlers()),
4949
'Signals' => \array_keys($workflow->getSignalHandlers()),
50-
// 'Updates' => $this->keys($workflow->getUpdateHandlers()),
50+
'VersioningBehavior' => $workflow->getVersioningBehavior()->value,
5151
];
5252

5353
$activityMap = static fn(ActivityPrototype $activity): array => [
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
/**
4+
* This file is part of Temporal package.
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
declare(strict_types=1);
11+
12+
namespace Temporal\Workflow;
13+
14+
use Doctrine\Common\Annotations\Annotation\Target;
15+
use Spiral\Attributes\NamedArgumentConstructor;
16+
use Temporal\Worker\Versioning\VersioningBehavior;
17+
18+
/**
19+
* Indicates the versioning behavior of the Workflow.
20+
* May only be applied to workflow implementations, not interfaces.
21+
*
22+
* @Annotation
23+
* @NamedArgumentConstructor
24+
* @Target({ "METHOD" })
25+
*
26+
* @see \Temporal\Api\Enums\V1\VersioningBehavior
27+
*/
28+
#[\Attribute(\Attribute::TARGET_METHOD), NamedArgumentConstructor]
29+
final class WorkflowVersioningBehavior
30+
{
31+
public function __construct(
32+
/**
33+
* The behavior to apply to this workflow.
34+
*
35+
* See {@link VersioningBehavior} for more information.
36+
*/
37+
public readonly VersioningBehavior $value,
38+
) {}
39+
}

0 commit comments

Comments
 (0)