Skip to content

Commit 1d45336

Browse files
[cross-repo from server#271] Conformance blocker: add namespaces host runner (#651)
1 parent afbfec3 commit 1d45336

3 files changed

Lines changed: 55 additions & 6 deletions

File tree

src/V2/Contracts/WorkflowControlPlane.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public function start(string $workflowType, ?string $instanceId = null, array $o
6363
*
6464
* Options:
6565
* - arguments: array<int, mixed> — positional signal arguments
66+
* - namespace: string|null — require the workflow instance to belong to this namespace
6667
* - command_context: \Workflow\V2\CommandContext|null — recorded command attribution/context
6768
* - strict_configured_type_validation: bool — fail closed when a configured workflow type mapping is now invalid
6869
*
@@ -95,6 +96,7 @@ public function signal(string $instanceId, string $name, array $options = []): a
9596
*
9697
* Options:
9798
* - arguments: array<int|string, mixed> — positional or named query arguments
99+
* - namespace: string|null — require the workflow instance to belong to this namespace
98100
* - strict_configured_type_validation: bool — fail closed when a configured workflow type mapping is now invalid
99101
*
100102
* @return array{
@@ -120,6 +122,7 @@ public function query(string $instanceId, string $name, array $options = []): ar
120122
*
121123
* Options:
122124
* - arguments: array<int|string, mixed> — positional or named update arguments
125+
* - namespace: string|null — require the workflow instance to belong to this namespace
123126
* - command_context: \Workflow\V2\CommandContext|null — recorded command attribution/context
124127
* - wait_for: 'accepted'|'completed'|null — accepted-only submit or completion wait
125128
* - wait_timeout_seconds: int|null — completion wait timeout
@@ -159,6 +162,7 @@ public function update(string $instanceId, string $name, array $options = []): a
159162
*
160163
* Options:
161164
* - reason: string|null — cancellation reason
165+
* - namespace: string|null — require the workflow instance to belong to this namespace
162166
* - command_context: \Workflow\V2\CommandContext|null — recorded command attribution/context
163167
* - strict_configured_type_validation: bool — fail closed when a configured workflow type mapping is now invalid
164168
*
@@ -186,6 +190,7 @@ public function cancel(string $instanceId, array $options = []): array;
186190
*
187191
* Options:
188192
* - reason: string|null — termination reason
193+
* - namespace: string|null — require the workflow instance to belong to this namespace
189194
* - command_context: \Workflow\V2\CommandContext|null — recorded command attribution/context
190195
* - strict_configured_type_validation: bool — fail closed when a configured workflow type mapping is now invalid
191196
*
@@ -216,6 +221,7 @@ public function terminate(string $instanceId, array $options = []): array;
216221
* Only the current run of an open workflow instance may be repaired.
217222
*
218223
* Options:
224+
* - namespace: string|null — require the workflow instance to belong to this namespace
219225
* - command_context: \Workflow\V2\CommandContext|null — recorded command attribution/context
220226
* - strict_configured_type_validation: bool — fail closed when a configured workflow type mapping is now invalid
221227
*
@@ -248,6 +254,7 @@ public function repair(string $instanceId, array $options = []): array;
248254
*
249255
* Options:
250256
* - reason: string|null — archive reason
257+
* - namespace: string|null — require the workflow instance to belong to this namespace
251258
* - command_context: \Workflow\V2\CommandContext|null — recorded command attribution/context
252259
* - strict_configured_type_validation: bool — fail closed when a configured workflow type mapping is now invalid
253260
*
@@ -280,6 +287,7 @@ public function archive(string $instanceId, array $options = []): array;
280287
*
281288
* Options:
282289
* - run_id: string|null — describe a specific run instead of current
290+
* - namespace: string|null — require the workflow instance to belong to this namespace
283291
*
284292
* @return array{
285293
* found: bool,

src/V2/Support/DefaultWorkflowControlPlane.php

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ public function archive(string $instanceId, array $options = []): array
676676
public function describe(string $instanceId, array $options = []): array
677677
{
678678
$runId = $options['run_id'] ?? null;
679+
$namespace = $this->namespaceOption($options);
679680

680681
$notFound = [
681682
'found' => false,
@@ -698,10 +699,15 @@ public function describe(string $instanceId, array $options = []): array
698699
];
699700

700701
try {
702+
$query = $this->instanceQuery()
703+
->with('currentRun');
704+
705+
if ($namespace !== null) {
706+
$query->where('namespace', $namespace);
707+
}
708+
701709
/** @var \Workflow\V2\Models\WorkflowInstance $instance */
702-
$instance = $this->instanceQuery()
703-
->with('currentRun')
704-
->findOrFail($instanceId);
710+
$instance = $query->findOrFail($instanceId);
705711
} catch (ModelNotFoundException) {
706712
return $notFound;
707713
}
@@ -871,9 +877,7 @@ private function commandAttributes(CommandContext $commandContext, array $attrib
871877
*/
872878
private function loadControlPlaneWorkflow(string $instanceId, array $options): array
873879
{
874-
$namespace = isset($options['namespace']) && is_string($options['namespace'])
875-
? $options['namespace']
876-
: null;
880+
$namespace = $this->namespaceOption($options);
877881

878882
try {
879883
$query = $this->instanceQuery();
@@ -983,6 +987,15 @@ private function resolveNamespace(array $options): ?string
983987
: null;
984988
}
985989

990+
private function namespaceOption(array $options): ?string
991+
{
992+
$namespace = $options['namespace'] ?? null;
993+
994+
return is_string($namespace) && trim($namespace) !== ''
995+
? trim($namespace)
996+
: null;
997+
}
998+
986999
private function notFoundControlPlaneResult(string $instanceId, string $idField): array
9871000
{
9881001
return [

tests/Feature/V2/V2WorkflowControlPlaneTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,34 @@ public function testDescribeActiveWorkflow(): void
651651
$this->assertTrue($result['actions']['can_terminate']);
652652
}
653653

654+
public function testDescribeCanBeScopedByNamespace(): void
655+
{
656+
$start = $this->controlPlane->start('remote-workflow-type', 'ctrl-plane-desc-ns-1', [
657+
'connection' => 'redis',
658+
'queue' => 'default',
659+
'namespace' => 'tenant-a',
660+
]);
661+
662+
$this->assertTrue($start['started']);
663+
664+
$visible = $this->controlPlane->describe('ctrl-plane-desc-ns-1', [
665+
'namespace' => 'tenant-a',
666+
]);
667+
668+
$this->assertTrue($visible['found']);
669+
$this->assertSame('tenant-a', $visible['namespace']);
670+
$this->assertIsArray($visible['run']);
671+
$this->assertSame($start['workflow_run_id'], $visible['run']['workflow_run_id']);
672+
673+
$hidden = $this->controlPlane->describe('ctrl-plane-desc-ns-1', [
674+
'namespace' => 'tenant-b',
675+
]);
676+
677+
$this->assertFalse($hidden['found']);
678+
$this->assertNull($hidden['run']);
679+
$this->assertSame('instance_not_found', $hidden['reason']);
680+
}
681+
654682
public function testDescribeTerminatedWorkflow(): void
655683
{
656684
$this->controlPlane->start('remote-workflow-type', 'ctrl-plane-desc-term-1', [

0 commit comments

Comments
 (0)