Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
00dad7f
feat: add VersioningBehavior enum to manage workflow versioning
roxblnfk Aug 12, 2025
cd0f0d9
refactor(tests): update Acceptance Tests Worker constructor to accept…
roxblnfk Aug 14, 2025
b763c12
chore: update Temporal Dev to ^1.4.1
roxblnfk Aug 15, 2025
53b64c0
feat: add WorkerDeploymentOptions class for configuring Worker Versio…
roxblnfk Aug 15, 2025
cac036d
style(php-cs-fixer): fix coding standards
Aug 15, 2025
52227b0
test(acceptance): reorganize versioning tests
roxblnfk Aug 18, 2025
95f26cc
test(acceptance): add Deployment Versioning test
roxblnfk Aug 18, 2025
fe7ebd6
feat: introduce WorkflowVersioningBehavior attribute and enhance work…
roxblnfk Aug 18, 2025
96dde24
refactor: update WorkerDeploymentOptions to use WorkerDeploymentVersi…
roxblnfk Aug 19, 2025
5cc27a3
test(acceptance): add Versioning test with Pinned behavior
roxblnfk Aug 19, 2025
09c3a8f
refactor: move VersioningBehavior to Common namespace
roxblnfk Aug 21, 2025
d14d66c
feat(WorkflowClient): add VersioningOverride feature;
roxblnfk Aug 21, 2025
d517b1a
chore: add phpdoc annotations
roxblnfk Aug 21, 2025
5f0dc26
chore: update RoadRunner version references to 2025.1.3
roxblnfk Aug 22, 2025
bca65f2
test: enhance versioning tests
roxblnfk Aug 22, 2025
c3f657b
refactor(Process): streamline context handling and initialization logic
roxblnfk Sep 12, 2025
e9b4f37
Merge branch 'refs/heads/master' into deployments
roxblnfk Sep 12, 2025
dfa10bb
chore: update psalm baseline and composer.json
roxblnfk Sep 12, 2025
0bb56a8
test(Deployment): refactor
roxblnfk Sep 12, 2025
9497fff
test(Acceptance): Sleep after Temporal restart
roxblnfk Sep 12, 2025
acdfa85
chore: Fix comments after review
roxblnfk Sep 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"roadrunner-php/roadrunner-api-dto": "^1.13.0",
"roadrunner-php/version-checker": "^1.0.1",
"spiral/attributes": "^3.1.8",
"spiral/roadrunner": "^2025.1.2",
"spiral/roadrunner": "^2025.1.3",
"spiral/roadrunner-cli": "^2.6",
"spiral/roadrunner-kv": "^4.3.1",
"spiral/roadrunner-worker": "^3.6.2",
Expand Down
4 changes: 2 additions & 2 deletions dload.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
temp-dir="./runtime"
>
<actions>
<download software="rr" version="^2025.1.2"/>
<download software="temporal" version="^1.3-priority"/>
<download software="rr" version="^2025.1.3"/>
<download software="temporal" version="^1.4.1"/>
<download software="temporal-tests-server"/>
</actions>
<registry>
Expand Down
40 changes: 31 additions & 9 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,14 @@
<code><![CDATA[non-empty-string]]></code>
</MoreSpecificReturnType>
</file>
<file src="src/Common/Versioning/WorkerDeploymentVersion.php">
<PossiblyNullArgument>
<code><![CDATA[$parts[1]]]></code>
</PossiblyNullArgument>
<PossiblyUndefinedArrayOffset>
<code><![CDATA[$parts[1]]]></code>
</PossiblyUndefinedArrayOffset>
</file>
<file src="src/DataConverter/DataConverter.php">
<MissingImmutableAnnotation>
<code><![CDATA[DataConverter]]></code>
Expand Down Expand Up @@ -547,8 +555,10 @@
</PropertyNotSetInConstructor>
</file>
<file src="src/Internal/Declaration/Graph/ClassNode.php">
<ImplicitToStringCast>
<code><![CDATA[list<array{class-string, \ReflectionMethod}>]]></code>
</ImplicitToStringCast>
<InvalidReturnType>
<code><![CDATA[\Traversable<ClassNode, \ReflectionMethod>]]></code>
<code><![CDATA[\Traversable<ClassNode>]]></code>
</InvalidReturnType>
<MissingClosureReturnType>
Expand Down Expand Up @@ -611,17 +621,16 @@
<code><![CDATA[$name]]></code>
<code><![CDATA[$retry]]></code>
</ArgumentTypeCoercion>
<RawObjectIteration>
<code><![CDATA[$group]]></code>
</RawObjectIteration>
<RedundantConditionGivenDocblockType>
<code><![CDATA[$retry !== null]]></code>
</RedundantConditionGivenDocblockType>
<UnnecessaryVarAnnotation>
<code><![CDATA[\ReflectionMethod]]></code>
</UnnecessaryVarAnnotation>
</file>
<file src="src/Internal/Declaration/Reader/WorkflowReader.php">
<ArgumentTypeCoercion>
<code><![CDATA[$contextualRetry]]></code>
<code><![CDATA[$method]]></code>
<code><![CDATA[$name]]></code>
<code><![CDATA[$retry]]></code>
</ArgumentTypeCoercion>
Expand All @@ -631,13 +640,12 @@
<InvalidReturnType>
<code><![CDATA[\Traversable<ActivityPrototype>]]></code>
</InvalidReturnType>
<RawObjectIteration>
<code><![CDATA[$group]]></code>
<code><![CDATA[$group]]></code>
</RawObjectIteration>
<RedundantConditionGivenDocblockType>
<code><![CDATA[$retry !== null]]></code>
</RedundantConditionGivenDocblockType>
<UnnecessaryVarAnnotation>
<code><![CDATA[\Traversable<class-string, \ReflectionMethod>]]></code>
</UnnecessaryVarAnnotation>
</file>
<file src="src/Internal/Declaration/WorkflowInstance/QueryDispatcher.php">
<PropertyNotSetInConstructor>
Expand Down Expand Up @@ -1451,6 +1459,15 @@
<code><![CDATA[run]]></code>
</MissingReturnType>
</file>
<file src="src/Worker/WorkerOptions.php">
<DeprecatedProperty>
<code><![CDATA[$self->buildID]]></code>
<code><![CDATA[$self->useBuildIDForVersioning]]></code>
</DeprecatedProperty>
<MissingConstructor>
<code><![CDATA[$deploymentOptions]]></code>
</MissingConstructor>
</file>
<file src="src/WorkerFactory.php">
<DeprecatedClass>
<code><![CDATA[new AnnotationReader()]]></code>
Expand Down Expand Up @@ -1557,4 +1574,9 @@
<code><![CDATA[NamedArgumentConstructor]]></code>
</DeprecatedClass>
</file>
<file src="src/Workflow/WorkflowVersioningBehavior.php">
<DeprecatedClass>
<code><![CDATA[NamedArgumentConstructor]]></code>
</DeprecatedClass>
</file>
</files>
27 changes: 26 additions & 1 deletion src/Client/WorkflowOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Temporal\Common\SearchAttributes\SearchAttributeKey;
use Temporal\Common\TypedSearchAttributes;
use Temporal\Common\Uuid;
use Temporal\Common\Versioning\VersioningOverride;
use Temporal\Common\WorkflowIdConflictPolicy;
use Temporal\DataConverter\DataConverterInterface;
use Temporal\Internal\Marshaller\Meta\Marshal;
Expand All @@ -32,8 +33,8 @@
use Temporal\Internal\Marshaller\Type\NullableType;
use Temporal\Internal\Support\DateInterval;
use Temporal\Internal\Support\Options;
use Temporal\Worker\WorkerFactoryInterface;
use Temporal\Worker\Worker;
use Temporal\Worker\WorkerFactoryInterface;

/**
* WorkflowOptions configuration parameters for starting a workflow execution.
Expand Down Expand Up @@ -182,6 +183,16 @@ final class WorkflowOptions extends Options
#[Marshal(name: 'Priority')]
public Priority $priority;

/**
* Override the version of the workflow.
*
* @since SDK 2.16.0
* @since RoadRunner 2025.1.3
* @internal Experimental
*/
#[Marshal(name: 'VersioningOverride')]
public ?VersioningOverride $versioningOverride = null;

/**
* @throws \Exception
*/
Expand Down Expand Up @@ -521,6 +532,20 @@ public function withStaticDetails(string $details): self
return $self;
}

/**
* Sets the versioning override to use when starting this workflow.
*
* @since SDK 2.16.0
* @since RoadRunner 2025.1.3
* @internal Experimental
*/
public function withVersioningOverride(?VersioningOverride $override): self
{
$self = clone $this;
$self->versioningOverride = $override;
return $self;
}

/**
* @internal
*/
Expand Down
77 changes: 77 additions & 0 deletions src/Common/Versioning/VersioningBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

declare(strict_types=1);

namespace Temporal\Common\Versioning;

/**
* Specifies when a workflow might move from a worker of one Build Id to another.
*
* Versioning Behavior specifies if and how a workflow execution moves between Worker Deployment
* Versions. The Versioning Behavior of a workflow execution is typically specified by the worker
* who completes the first task of the execution, but is also overridable manually for new and
* existing workflows (see VersioningOverride).
* Experimental. Worker Deployments are experimental and might significantly change in the future.
*
* @see \Temporal\Api\Enums\V1\VersioningBehavior
*
* @since SDK 2.16.0
* @since RoadRunner 2025.1.3
* @internal Experimental
*/
enum VersioningBehavior: int
{
/**
* An unspecified versioning behavior. By default, workers opting into worker versioning will be
* required to specify a behavior.
*/
case Unspecified = 0;

/**
* The workflow will be pinned to the current Build ID unless manually moved.
*
* Workflow will start on the Current Deployment Version of its Task Queue, and then
* will be pinned to that same Deployment Version until completion (the Version that
* this Workflow is pinned to is specified in `versioning_info.version`).
* This behavior eliminates most of compatibility concerns users face when changing their code.
* Patching is not needed when pinned workflows code change.
* Can be overridden explicitly via `UpdateWorkflowExecutionOptions` API to move the
* execution to another Deployment Version.
* Activities of `Pinned` workflows are sent to the same Deployment Version. Exception to this
* would be when the activity Task Queue workers are not present in the workflow's Deployment
* Version, in which case the activity will be sent to the Current Deployment Version of its own
* task queue.
*/
case Pinned = 1;

/**
* The workflow will automatically move to the latest version (default Build ID of the task queue)
* when the next task is dispatched.
*
* Workflow will automatically move to the Current Deployment Version of its Task Queue when the
* next workflow task is dispatched.
* AutoUpgrade behavior is suitable for long-running workflows as it allows them to move to the
* latest Deployment Version, but the user still needs to use Patching to keep the new code
* compatible with prior versions for changed workflow types.
* Activities of `AUTO_UPGRADE` workflows are sent to the Deployment Version of the workflow
* execution (as specified in versioning_info.version based on the last completed
* workflow task). Exception to this would be when the activity Task Queue workers are not
* present in the workflow's Deployment Version, in which case, the activity will be sent to a
* different Deployment Version according to the Current Deployment Version of its own task
* queue.
* Workflows stuck on a backlogged activity will still auto-upgrade if the Current Deployment
* Version of their Task Queue changes, without having to wait for the backlogged activity to
* complete on the old Version.
*/
case AutoUpgrade = 2;

public static function tryFromName(?string $name): ?self
{
return match ($name) {
'Unspecified', null => self::Unspecified,
'Pinned' => self::Pinned,
'AutoUpgrade' => self::AutoUpgrade,
default => null,
};
}
}
48 changes: 48 additions & 0 deletions src/Common/Versioning/VersioningOverride.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

/**
* This file is part of Temporal package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Temporal\Common\Versioning;

/**
* Represents the override of a worker's versioning behavior for a workflow execution.
*
* @since SDK 2.16.0
* @since RoadRunner 2025.1.3
* @internal Experimental
*/
final class VersioningOverride
{
private function __construct(
public readonly VersioningBehavior $behavior,
public readonly ?WorkerDeploymentVersion $version = null,
) {}

/**
* The Workflow will be pinned to a specific deployment version.
*/
public static function pinned(WorkerDeploymentVersion $version): self
{
return new self(
VersioningBehavior::Pinned,
$version,
);
}

/**
* The Workflow will auto-upgrade to the current deployment version on the next workflow task.
*/
public static function autoUpgrade(): self
{
return new self(
VersioningBehavior::AutoUpgrade,
);
}
}
79 changes: 79 additions & 0 deletions src/Common/Versioning/WorkerDeploymentVersion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

declare(strict_types=1);

namespace Temporal\Common\Versioning;

use Temporal\Exception\InvalidArgumentException;
use Temporal\Internal\Marshaller\Meta\Marshal;
use Temporal\Internal\Traits\CloneWith;

/**
* Represents the version of a specific worker deployment.
*
* @see \Temporal\Api\Deployment\V1\WorkerDeploymentVersion
*
* @since SDK 2.16.0
* @since RoadRunner 2025.1.3
* @internal Experimental
*/
class WorkerDeploymentVersion implements \Stringable
{
use CloneWith;

private function __construct(
/**
* A unique identifier for this Version within the Deployment it is a part of.
* Not necessarily unique within the namespace.
* The combination of {@see $deployment_name} and {@see $buildId} uniquely identifies this
* Version within the namespace, because Deployment names are unique within a namespace.
*/
#[Marshal('DeploymentName')]
public readonly string $deploymentName,

/**
* Identifies the Worker Deployment this Version is part of.
*/
#[Marshal('BuildId')]
public readonly string $buildId,
) {}

/**
* Create a new worker deployment version with the given deployment name and build ID.
*
* @param non-empty-string $deploymentName The name of the worker deployment. Must not contain a ".".
* @param non-empty-string $buildId The build ID of the worker deployment.
*
* @throws InvalidArgumentException if the deployment name or build ID is empty or invalid.
*/
public static function new(string $deploymentName, string $buildId): self
{
return new self($deploymentName, $buildId);
}

/**
* Build a worker deployment version from a canonical string representation.
*
* @param non-empty-string $canonicalString The canonical string representation of the worker deployment version,
* formatted as "deploymentName.buildId". Deployment name must not have a "." in it.
*
* @throws InvalidArgumentException if the input string is not in the expected format.
*/
public static function fromString(string $canonicalString): self
{
$parts = \explode('.', $canonicalString, 2);
\count($parts) === 2 or throw new InvalidArgumentException(
"Invalid canonical string format. Expected 'deploymentName.buildId'",
);

return new self($parts[0], $parts[1]);
}

/**
* @return non-empty-string canonical string representation of this worker deployment version.
*/
public function __toString()
{
return "{$this->deploymentName}.{$this->buildId}";
}
}
Loading
Loading