Skip to content

Commit 8cdcc18

Browse files
authored
Merge pull request #417: Expose WorkflowIdConflictPolicy
2 parents 0179c48 + cd9964b commit 8cdcc18

File tree

5 files changed

+87
-4
lines changed

5 files changed

+87
-4
lines changed

src/Client/Workflow/WorkflowExecutionDescription.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*/
1616
final class WorkflowExecutionDescription
1717
{
18+
/**
19+
* @internal
20+
*/
1821
public function __construct(
1922
public readonly WorkflowExecutionInfo $info,
2023
) {

src/Client/WorkflowOptions.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Temporal\Common\MethodRetry;
2222
use Temporal\Common\RetryOptions;
2323
use Temporal\Common\Uuid;
24+
use Temporal\Common\WorkflowIdConflictPolicy;
2425
use Temporal\DataConverter\DataConverterInterface;
2526
use Temporal\Internal\Marshaller\Meta\Marshal;
2627
use Temporal\Internal\Marshaller\Type\ArrayType;
@@ -98,12 +99,19 @@ final class WorkflowOptions extends Options
9899
public \DateInterval $workflowTaskTimeout;
99100

100101
/**
101-
* Whether server allow reuse of workflow ID, can be useful for deduplication logic.
102-
* If set to {@see IdReusePolicy::POLICY_REJECT_DUPLICATE}.
102+
* Whether server allow reuse of workflow ID.
103+
*
104+
* Can be useful for deduplication logic if set to {@see IdReusePolicy::POLICY_REJECT_DUPLICATE}.
103105
*/
104106
#[Marshal(name: 'WorkflowIDReusePolicy')]
105107
public int $workflowIdReusePolicy = IdReusePolicy::POLICY_ALLOW_DUPLICATE_FAILED_ONLY;
106108

109+
/**
110+
* Defines how to resolve an ID conflict with a *running* workflow.
111+
*/
112+
#[Marshal(name: 'WorkflowIdConflictPolicy')]
113+
public WorkflowIdConflictPolicy $workflowIdConflictPolicy = WorkflowIdConflictPolicy::Unspecified;
114+
107115
/**
108116
* Optional retry policy for workflow. If a retry policy is specified, in
109117
* case of workflow failure server will start new workflow execution if
@@ -319,8 +327,8 @@ public function withWorkflowStartDelay($delay): self
319327
}
320328

321329
/**
322-
* Specifies server behavior if a completed workflow with the same id
323-
* exists. Note that under no conditions Temporal allows two workflows
330+
* Specifies server behavior if a *closed* workflow with the same id exists.
331+
* Note that under no conditions Temporal allows two workflows
324332
* with the same namespace and workflow id run simultaneously.
325333
*
326334
* - {@see IdReusePolicy::AllowDuplicateFailedOnly}: Is a default
@@ -347,6 +355,21 @@ public function withWorkflowIdReusePolicy(IdReusePolicy|int $policy): self
347355
return $self;
348356
}
349357

358+
/**
359+
* Defines how to resolve an ID conflict with a *running* workflow.
360+
*
361+
* @psalm-suppress ImpureMethodCall
362+
*
363+
* @return $this
364+
*/
365+
#[Pure]
366+
public function withWorkflowIdConflictPolicy(WorkflowIdConflictPolicy $policy): self
367+
{
368+
$self = clone $this;
369+
$self->workflowIdConflictPolicy = $policy;
370+
return $self;
371+
}
372+
350373
/**
351374
* RetryOptions that define how child workflow is retried in case of
352375
* failure. Default is null which is no reties.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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\Common;
13+
14+
/**
15+
* Defines what to do when trying to start a workflow with the same workflow id as a *running* workflow.
16+
* Note that it is *never* valid to have two actively running instances of the same workflow id.
17+
*
18+
* @see IdReusePolicy for handling workflow id duplication with a *closed* workflow.
19+
* @see \Temporal\Api\Enums\V1\WorkflowIdConflictPolicy
20+
*/
21+
enum WorkflowIdConflictPolicy: int
22+
{
23+
case Unspecified = 0;
24+
25+
/**
26+
* Don't start a new workflow; instead return `WorkflowExecutionAlreadyStartedFailure`.
27+
*/
28+
case Fail = 1;
29+
30+
/**
31+
* Don't start a new workflow; instead return a workflow handle for the running workflow.
32+
*/
33+
case UseExisting = 2;
34+
35+
/**
36+
* Terminate the running workflow before starting a new one.
37+
*/
38+
case TerminateExisting = 3;
39+
40+
}

src/Internal/Client/WorkflowStarter.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ private function configureExecutionRequest(
194194
->setCronSchedule($options->cronSchedule ?? '')
195195
->setRetryPolicy($options->retryOptions ? $options->retryOptions->toWorkflowRetryPolicy() : null)
196196
->setWorkflowIdReusePolicy($options->workflowIdReusePolicy)
197+
->setWorkflowIdConflictPolicy($options->workflowIdConflictPolicy->value)
197198
->setWorkflowRunTimeout(DateInterval::toDuration($options->workflowRunTimeout))
198199
->setWorkflowExecutionTimeout(DateInterval::toDuration($options->workflowExecutionTimeout))
199200
->setWorkflowTaskTimeout(DateInterval::toDuration($options->workflowTaskTimeout))

tests/Unit/DTO/WorkflowOptionsTestCase.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Temporal\Common\IdReusePolicy;
1919
use Temporal\Common\RetryOptions;
2020
use Temporal\Common\Uuid;
21+
use Temporal\Common\WorkflowIdConflictPolicy;
2122
use Temporal\DataConverter\DataConverter;
2223

2324
class WorkflowOptionsTestCase extends AbstractDTOMarshalling
@@ -38,6 +39,10 @@ public function testMarshalling(): void
3839
'WorkflowStartDelay' => 0,
3940
'WorkflowTaskTimeout' => 0,
4041
'WorkflowIDReusePolicy' => 2,
42+
'WorkflowIdConflictPolicy' => [
43+
'name' => 'Unspecified',
44+
'value' => 0,
45+
],
4146
'RetryPolicy' => null,
4247
'CronSchedule' => null,
4348
'Memo' => null,
@@ -125,6 +130,17 @@ public function testWorkflowIdReusePolicyChangesNotMutateStateUsingEnum(): void
125130
$this->assertSame(IdReusePolicy::AllowDuplicateFailedOnly->value, $dto->workflowIdReusePolicy);
126131
}
127132

133+
public function testWorkflowIdConflictPolicy(): void
134+
{
135+
$dto = new WorkflowOptions();
136+
137+
$this->assertNotSame($dto, $newDto = $dto->withWorkflowIdConflictPolicy(
138+
WorkflowIdConflictPolicy::Fail
139+
));
140+
$this->assertSame(WorkflowIdConflictPolicy::Unspecified, $dto->workflowIdConflictPolicy);
141+
$this->assertSame(WorkflowIdConflictPolicy::Fail, $newDto->workflowIdConflictPolicy);
142+
}
143+
128144
public function testRetryOptionsChangesNotMutateState(): void
129145
{
130146
$dto = new WorkflowOptions();

0 commit comments

Comments
 (0)