Skip to content

Commit 0c2a314

Browse files
authored
Merge pull request #578: update Workflow description info
2 parents 60a0c66 + 414aca4 commit 0c2a314

File tree

13 files changed

+239
-34
lines changed

13 files changed

+239
-34
lines changed

psalm-baseline.xml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<files psalm-version="6.7.1@a2f190972555ea01b0cfcc1913924d6c5fc1a64e">
2+
<files psalm-version="6.8.8@1361cd33008feb3ae2b4a93f1860e14e538ec8c2">
33
<file src="src/Activity.php">
44
<ImplicitToStringCast>
55
<code><![CDATA[$type]]></code>
@@ -370,9 +370,6 @@
370370
<InvalidNullableReturnType>
371371
<code><![CDATA[Failure]]></code>
372372
</InvalidNullableReturnType>
373-
<InvalidOperand>
374-
<code><![CDATA[\count($arg)]]></code>
375-
</InvalidOperand>
376373
<NullableReturnStatement>
377374
<code><![CDATA[$e->getFailure()]]></code>
378375
</NullableReturnStatement>
@@ -673,6 +670,13 @@
673670
<code><![CDATA[setDataConverter]]></code>
674671
</UndefinedInterfaceMethod>
675672
</file>
673+
<file src="src/Internal/Mapper/WorkflowExecutionInfoMapper.php">
674+
<ArgumentTypeCoercion>
675+
<code><![CDATA[$message->getTaskQueue()]]></code>
676+
<code><![CDATA[(int) $message->getHistorySizeBytes()]]></code>
677+
<code><![CDATA[(int) $message->getStateTransitionCount()]]></code>
678+
</ArgumentTypeCoercion>
679+
</file>
676680
<file src="src/Internal/Marshaller/Mapper/AttributeMapper.php">
677681
<MissingClosureParamType>
678682
<code><![CDATA[$value]]></code>

src/Internal/Mapper/WorkflowExecutionInfoMapper.php

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Temporal\Common\WorkerVersionStamp as WorkerVersionStampDto;
1515
use Temporal\DataConverter\DataConverterInterface;
1616
use Temporal\DataConverter\EncodedCollection;
17+
use Temporal\Internal\Support\DateInterval;
1718
use Temporal\Workflow\ResetPointInfo as ResetPointInfoDto;
1819
use Temporal\Workflow\WorkflowExecution as WorkflowExecutionDto;
1920
use Temporal\Workflow\WorkflowExecutionInfo as WorkflowExecutionInfoDto;
@@ -36,6 +37,8 @@ public function fromMessage(WorkflowExecutionInfo $message): WorkflowExecutionIn
3637
$wfType = new WorkflowType();
3738
/** @psalm-suppress InaccessibleProperty */
3839
$wfType->name = $type->getName();
40+
$executionDuration = $message->getExecutionDuration();
41+
$executionDuration !== null and $executionDuration = DateInterval::parse($executionDuration);
3942

4043
return new WorkflowExecutionInfoDto(
4144
execution: $execution,
@@ -54,6 +57,9 @@ public function fromMessage(WorkflowExecutionInfo $message): WorkflowExecutionIn
5457
stateTransitionCount: (int) $message->getStateTransitionCount(),
5558
historySizeBytes: (int) $message->getHistorySizeBytes(),
5659
mostRecentWorkerVersionStamp: $this->prepareWorkerVersionStamp($message->getMostRecentWorkerVersionStamp()),
60+
executionDuration: $executionDuration,
61+
rootExecution: $this->prepareWorkflowExecution($message->getRootExecution()),
62+
firstRunId: $message->getFirstRunId(),
5763
);
5864
}
5965

@@ -93,14 +99,12 @@ private function prepareSearchAttributes(?SearchAttributes $searchAttributes): E
9399

94100
private function prepareWorkflowExecution(?WorkflowExecution $execution): ?WorkflowExecutionDto
95101
{
96-
if ($execution === null) {
97-
return null;
98-
}
99-
100-
return new WorkflowExecutionDto(
101-
id: $execution->getWorkflowId(),
102-
runId: $execution->getRunId(),
103-
);
102+
return $execution === null
103+
? null
104+
: new WorkflowExecutionDto(
105+
id: $execution->getWorkflowId(),
106+
runId: $execution->getRunId(),
107+
);
104108
}
105109

106110
/**

src/Workflow/WorkflowExecutionInfo.php

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,14 @@
1010
use Temporal\Workflow\ResetPointInfo as ResetPointInfoDto;
1111

1212
/**
13-
* DTO that contains detailed information about Workflow Execution.
13+
* DTO that contains basic information about Workflow Execution.
1414
*
1515
* @see \Temporal\Api\Workflow\V1\WorkflowExecutionInfo
1616
* @psalm-immutable
1717
*/
1818
#[Immutable]
1919
final class WorkflowExecutionInfo
2020
{
21-
/**
22-
* @param array<ResetPointInfoDto> $autoResetPoints
23-
*/
2421
public function __construct(
2522
public readonly WorkflowExecution $execution,
2623
public readonly WorkflowType $type,
@@ -33,10 +30,70 @@ public function __construct(
3330
public readonly ?\DateTimeInterface $executionTime,
3431
public readonly EncodedCollection $memo,
3532
public readonly EncodedCollection $searchAttributes,
33+
34+
/**
35+
* @var array<ResetPointInfoDto>
36+
*/
3637
public readonly array $autoResetPoints,
38+
39+
/**
40+
* @var non-empty-string
41+
*/
3742
public readonly string $taskQueue,
43+
44+
/**
45+
* @var int<1, max>
46+
*/
3847
public readonly int $stateTransitionCount,
48+
49+
/**
50+
* @var int<1, max>
51+
*/
3952
public readonly int $historySizeBytes,
53+
54+
/**
55+
* If set, the most recent worker version stamp that appeared in a workflow task completion
56+
* @deprecated
57+
*/
4058
public readonly ?WorkerVersionStamp $mostRecentWorkerVersionStamp,
59+
60+
/**
61+
* Workflow execution duration is defined as difference between close time and execution time.
62+
* This field is only populated if the workflow is closed.
63+
*/
64+
public readonly ?\DateInterval $executionDuration,
65+
66+
/**
67+
* Contains information about the root workflow execution.
68+
*
69+
* The root workflow execution is defined as follows:
70+
* 1. A workflow without parent workflow is its own root workflow.
71+
* 2. A workflow that has a parent workflow has the same root workflow as its parent workflow.
72+
*
73+
* Note: workflows continued as new or reseted may or may not have parents, check examples below.
74+
*
75+
* Examples:
76+
* Scenario 1: Workflow W1 starts child workflow W2, and W2 starts child workflow W3.
77+
* - The root workflow of all three workflows is W1.
78+
* Scenario 2: Workflow W1 starts child workflow W2, and W2 continued as new W3.
79+
* - The root workflow of all three workflows is W1.
80+
* Scenario 3: Workflow W1 continued as new W2.
81+
* - The root workflow of W1 is W1 and the root workflow of W2 is W2.
82+
* Scenario 4: Workflow W1 starts child workflow W2, and W2 is reseted, creating W3
83+
* - The root workflow of all three workflows is W1.
84+
* Scenario 5: Workflow W1 is reseted, creating W2.
85+
* - The root workflow of W1 is W1 and the root workflow of W2 is W2.
86+
*/
87+
public readonly ?WorkflowExecution $rootExecution,
88+
89+
/**
90+
* The first run ID in the execution chain.
91+
* Executions created via the following operations are considered to be in the same chain
92+
* - ContinueAsNew
93+
* - Workflow Retry
94+
* - Workflow Reset
95+
* - Cron Schedule
96+
*/
97+
public readonly string $firstRunId,
4198
) {}
4299
}

tests/Acceptance/App/Runtime/RRStarter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function __construct(
1616
private State $runtime,
1717
) {
1818
$this->environment = Environment::create();
19-
// \register_shutdown_function(fn() => $this->stop());
19+
\register_shutdown_function(fn() => $this->stop());
2020
}
2121

2222
public function start(): void

tests/Acceptance/App/Runtime/TemporalStarter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ final class TemporalStarter
1515
public function __construct()
1616
{
1717
$this->environment = Environment::create();
18-
// \register_shutdown_function(fn() => $this->stop());
18+
\register_shutdown_function(fn() => $this->stop());
1919
}
2020

2121
public function start(): void
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Temporal\Tests\Acceptance\Extra\Client\WorkflowClient;
6+
7+
use PHPUnit\Framework\Attributes\Test;
8+
use Temporal\Client\WorkflowClientInterface;
9+
use Temporal\Client\WorkflowOptions;
10+
use Temporal\Tests\Acceptance\App\Runtime\Feature;
11+
use Temporal\Tests\Acceptance\App\TestCase;
12+
use Temporal\Workflow;
13+
use Temporal\Workflow\SignalMethod;
14+
use Temporal\Workflow\WorkflowInterface;
15+
use Temporal\Workflow\WorkflowMethod;
16+
17+
class WorkflowClientTest extends TestCase
18+
{
19+
#[Test]
20+
public function describeWorkflowExecution(
21+
WorkflowClientInterface $client,
22+
Feature $feature,
23+
): void {
24+
$stub = $client->newUntypedWorkflowStub(
25+
'Extra_Client_WorkflowClient',
26+
WorkflowOptions::new()
27+
->withTaskQueue($feature->taskQueue)
28+
->withSearchAttributes([
29+
'testFloat' => 1.1,
30+
'testInt' => -2,
31+
'testBool' => false,
32+
'testText' => 'foo',
33+
'testKeyword' => 'bar',
34+
'testKeywordList' => ['baz'],
35+
'testDatetime' => new \DateTimeImmutable('2019-01-01T00:00:00Z'),
36+
])
37+
->withMemo([
38+
'key1' => 'value1',
39+
'key2' => 'value2',
40+
'key3' => ['foo' => 'bar'],
41+
42 => 'value4',
42+
]),
43+
);
44+
$client->start($stub);
45+
46+
// Describe running workflow
47+
$description = $stub->describe();
48+
49+
self::assertInstanceOf(\DateTimeInterface::class, $description->info->startTime);
50+
self::assertNull($description->info->closeTime);
51+
self::assertSame(Workflow\WorkflowExecutionStatus::Running, $description->info->status);
52+
self::assertGreaterThanOrEqual(2, $description->info->historyLength);
53+
self::assertNull($description->info->parentExecution);
54+
self::assertNotNull($description->info->executionTime);
55+
self::assertCount(7, $description->info->searchAttributes);
56+
self::assertCount(4, $description->info->memo);
57+
self::assertNull($description->info->executionDuration);
58+
self::assertSame($description->info->firstRunId, $description->info->execution->getRunID());
59+
self::assertEquals($description->info->execution, $description->info->rootExecution);
60+
61+
$stub->signal('my_signal', 'test');
62+
self::assertSame('test', $stub->getResult());
63+
64+
$description = $stub->describe();
65+
self::assertNotNull($description->info->executionDuration);
66+
}
67+
}
68+
69+
70+
#[WorkflowInterface]
71+
class FeatureWorkflow
72+
{
73+
private string $value = '';
74+
75+
#[WorkflowMethod('Extra_Client_WorkflowClient')]
76+
public function run()
77+
{
78+
yield Workflow::await(fn(): bool => $this->value !== '');
79+
return $this->value;
80+
}
81+
82+
#[SignalMethod('my_signal')]
83+
public function mySignal(string $arg): void
84+
{
85+
$this->value = $arg;
86+
}
87+
}

tests/Acceptance/Extra/Schedule/ScheduleClientTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Temporal\Tests\Acceptance\Extra\Update\ScheduleClient;
5+
namespace Temporal\Tests\Acceptance\Extra\Schedule\ScheduleClient;
66

77
use PHPUnit\Framework\Attributes\Test;
88
use Temporal\Client\Schedule\Action\StartWorkflowAction;

tests/Acceptance/Extra/Schedule/ScheduleUpdateTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Temporal\Tests\Acceptance\Extra\Update\ScheduleUpdate;
5+
namespace Temporal\Tests\Acceptance\Extra\Schedule\ScheduleUpdate;
66

77
use PHPUnit\Framework\Attributes\Test;
88
use Temporal\Client\Schedule\Action\StartWorkflowAction;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Temporal\Tests\Acceptance\Extra\Workflow\RootWorkflowExecution;
6+
7+
use PHPUnit\Framework\Attributes\Test;
8+
use Temporal\Client\WorkflowStubInterface;
9+
use Temporal\Tests\Acceptance\App\Attribute\Stub;
10+
use Temporal\Tests\Acceptance\App\TestCase;
11+
use Temporal\Workflow;
12+
use Temporal\Workflow\WorkflowInterface;
13+
use Temporal\Workflow\WorkflowMethod;
14+
15+
class RootWorkflowExecutionTest extends TestCase
16+
{
17+
#[Test]
18+
public static function check(#[Stub('Extra_Workflow_RootWorkflowExecution')]WorkflowStubInterface $stub): void
19+
{
20+
self::markTestSkipped('Waiting https://github.com/temporalio/sdk-go/issues/1848');
21+
self::assertSame('Test', $stub->getResult());
22+
}
23+
}
24+
25+
#[WorkflowInterface]
26+
class MainWorkflow
27+
{
28+
#[WorkflowMethod('Extra_Workflow_RootWorkflowExecution')]
29+
public function run()
30+
{
31+
return yield Workflow::newChildWorkflowStub(ChildWorkflow::class)
32+
->run('Test');
33+
}
34+
}
35+
36+
#[WorkflowInterface]
37+
class ChildWorkflow
38+
{
39+
#[WorkflowMethod('Extra_Workflow_RootWorkflowExecution_Child')]
40+
public function run(string $input)
41+
{
42+
return yield Workflow::newChildWorkflowStub(ChildWorkflow2::class)
43+
->run($input);
44+
}
45+
}
46+
47+
#[WorkflowInterface]
48+
class ChildWorkflow2
49+
{
50+
#[WorkflowMethod('Extra_Workflow_RootWorkflowExecution_Child2')]
51+
public function run(string $input)
52+
{
53+
return $input;
54+
}
55+
}

tests/Acceptance/Harness/ChildWorkflow/ResultTest.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,8 @@ class MainWorkflow
2727
#[WorkflowMethod('Harness_ChildWorkflow_Result')]
2828
public function run()
2929
{
30-
return yield Workflow::newChildWorkflowStub(
31-
ChildWorkflow::class,
32-
// TODO: remove after https://github.com/temporalio/sdk-php/issues/451 is fixed
33-
Workflow\ChildWorkflowOptions::new()->withTaskQueue(Workflow::getInfo()->taskQueue),
34-
)->run('Test');
30+
return yield Workflow::newChildWorkflowStub(ChildWorkflow::class)
31+
->run('Test');
3532
}
3633
}
3734

0 commit comments

Comments
 (0)