Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions src/Common/RetryOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class RetryOptions extends Options
* is 1.0 then it is used for all retries.
*/
#[Marshal(name: 'initial_interval', type: DurationJsonType::class, nullable: true)]
#[Marshal(name: 'InitialInterval', type: DurationJsonType::class, nullable: true)]
public ?\DateInterval $initialInterval = self::DEFAULT_INITIAL_INTERVAL;

/**
Expand All @@ -77,6 +78,7 @@ class RetryOptions extends Options
* Note: Must be greater than 1.0
*/
#[Marshal(name: 'backoff_coefficient')]
#[Marshal(name: 'BackoffCoefficient')]
public float $backoffCoefficient = self::DEFAULT_BACKOFF_COEFFICIENT;

/**
Expand All @@ -86,6 +88,7 @@ class RetryOptions extends Options
* Default is 100x of {@see $initialInterval}.
*/
#[Marshal(name: 'maximum_interval', type: DurationJsonType::class, nullable: true)]
#[Marshal(name: 'MaximumInterval', type: DurationJsonType::class, nullable: true)]
public ?\DateInterval $maximumInterval = self::DEFAULT_MAXIMUM_INTERVAL;

/**
Expand All @@ -96,6 +99,7 @@ class RetryOptions extends Options
* @var int<0, max>
*/
#[Marshal(name: 'maximum_attempts')]
#[Marshal(name: 'MaximumAttempts')]
public int $maximumAttempts = self::DEFAULT_MAXIMUM_ATTEMPTS;

/**
Expand All @@ -105,6 +109,7 @@ class RetryOptions extends Options
* @var ExceptionsList
*/
#[Marshal(name: 'non_retryable_error_types')]
#[Marshal(name: 'NonRetryableErrorTypes')]
public array $nonRetryableExceptions = self::DEFAULT_NON_RETRYABLE_EXCEPTIONS;

public function mergeWith(?MethodRetry $retry = null): self
Expand Down
3 changes: 0 additions & 3 deletions src/Internal/Marshaller/MarshallingRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@

use Temporal\Internal\Marshaller\Type\TypeInterface;

/**
* @internal
*/
class MarshallingRule
{
/**
Expand Down
4 changes: 4 additions & 0 deletions src/Internal/Marshaller/Type/ArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ public static function makeRule(\ReflectionProperty $property): ?MarshallingRule
*/
public function parse($value, $current): array
{
if ($value === null) {
return [];
}

if (!\is_array($value)) {
throw new \InvalidArgumentException(\sprintf(self::ERROR_INVALID_TYPE, \get_debug_type($value)));
}
Expand Down
7 changes: 7 additions & 0 deletions src/Workflow/WorkflowInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Temporal\Client\ClientOptions;
use Temporal\Common\CronSchedule;
use Temporal\Common\Priority;
use Temporal\Common\RetryOptions;
use Temporal\Common\TypedSearchAttributes;
use Temporal\Internal\Marshaller\Meta\Marshal;
use Temporal\Internal\Marshaller\Type\ArrayType;
Expand Down Expand Up @@ -143,6 +144,12 @@ final class WorkflowInfo
#[Marshal(name: 'Priority')]
public Priority $priority;

/**
* @since SDK 2.16.0
*/
#[Marshal(name: 'RetryPolicy')]
public ?RetryOptions $retryOptions = null;

/**
* WorkflowInfo constructor.
*/
Expand Down
78 changes: 78 additions & 0 deletions tests/Acceptance/Extra/Activity/ActivityInfoTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

declare(strict_types=1);

namespace Temporal\Tests\Acceptance\Extra\Activity\ActivityInfo;

use PHPUnit\Framework\Attributes\Test;
use React\Promise\PromiseInterface;
use Temporal\Activity;
use Temporal\Client\WorkflowStubInterface;
use Temporal\Common\RetryOptions;
use Temporal\Tests\Acceptance\App\Attribute\Stub;
use Temporal\Tests\Acceptance\App\TestCase;
use Temporal\Workflow;
use Temporal\Workflow\WorkflowInterface;
use Temporal\Workflow\WorkflowMethod;

class ActivityInfoTest extends TestCase
{
#[Test]
public static function retryPolicy(
#[Stub('Extra_Activity_ActivityInfo', args: [TestWorkflow::ARG_RETRY_OPTIONS])]
WorkflowStubInterface $stub,
): void {
self::markTestSkipped('See https://github.com/temporalio/sdk-php/issues/602');

$result = $stub->getResult(type: 'array');
self::assertSame([
"initial_interval" => ['seconds' => 1, 'nanos' => 0],
"backoff_coefficient" => 3,
"maximum_interval" => ['seconds' => 120, 'nanos' => 0],
"maximum_attempts" => 20,
"non_retryable_error_types" => [],
], $result);
}
}


#[WorkflowInterface]
class TestWorkflow
{
public const ARG_RETRY_OPTIONS = 'retryPolicy';

#[WorkflowMethod(name: "Extra_Activity_ActivityInfo")]
public function handle(string $arg)
{
return yield match ($arg) {
self::ARG_RETRY_OPTIONS => $this->getRetryOptions(),
};
}

private function getRetryOptions(): PromiseInterface
{
return Workflow::newActivityStub(
TestActivity::class,
Activity\ActivityOptions::new()
->withRetryOptions(
RetryOptions::new()
->withMaximumAttempts(20)
->withBackoffCoefficient(3.0)
->withInitialInterval('1 second')
->withMaximumInterval('2 minutes'),
)
->withScheduleToCloseTimeout(10),
)
->retryOptions();
}
}

#[Activity\ActivityInterface(prefix: 'Extra_Activity_ActivityInfo.')]
class TestActivity
{
#[Activity\ActivityMethod]
public function retryOptions()
{
return Activity::getInfo()->retryOptions;
}
}
58 changes: 0 additions & 58 deletions tests/Acceptance/Extra/Workflow/RootWorkflowExecutionTest.php

This file was deleted.

84 changes: 84 additions & 0 deletions tests/Acceptance/Extra/Workflow/WorkflowInfoTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

declare(strict_types=1);

namespace Temporal\Tests\Acceptance\Extra\Workflow\WorkflowInfo;

use PHPUnit\Framework\Attributes\Test;
use Temporal\Client\WorkflowStubInterface;
use Temporal\Tests\Acceptance\App\Attribute\RetryOptions;
use Temporal\Tests\Acceptance\App\Attribute\Stub;
use Temporal\Tests\Acceptance\App\TestCase;
use Temporal\Workflow;
use Temporal\Workflow\WorkflowInterface;
use Temporal\Workflow\WorkflowMethod;

class WorkflowInfoTest extends TestCase
{
#[Test]
public static function rootWorkflowExecution(
#[Stub('Extra_Workflow_WorkflowInfo', args: [MainWorkflow::ARG_ROOT_EXECUTION])]
WorkflowStubInterface $stub,
): void {
$result = $stub->getResult(type: 'array');
self::assertSame([
'ID' => $stub->getExecution()->getID(),
'RunID' => $stub->getExecution()->getRunID(),
], $result);
}

#[Test]
public static function retryOptions(
#[Stub('Extra_Workflow_WorkflowInfo', args: [MainWorkflow::ARG_RETRY_OPTIONS], retryOptions: new RetryOptions(
backoffCoefficient: 3.0,
maximumInterval: '2 minutes',
maximumAttempts: 10,
))]
WorkflowStubInterface $stub,
): void {
$result = $stub->getResult(type: 'array');
self::assertEquals([
"initial_interval" => ['seconds' => 1, 'nanos' => 0],
"backoff_coefficient" => 3,
"maximum_interval" => ['seconds' => 120, 'nanos' => 0],
"maximum_attempts" => 10,
"non_retryable_error_types" => [],
], $result);
}
}

#[WorkflowInterface]
class MainWorkflow
{
public const ARG_RETRY_OPTIONS = 'retryPolicy';
public const ARG_ROOT_EXECUTION = 'rootExecution';

#[WorkflowMethod('Extra_Workflow_WorkflowInfo')]
public function run($arg)
{
return yield match ($arg) {
self::ARG_ROOT_EXECUTION => Workflow::newChildWorkflowStub(ChildWorkflow::class)->run(),
self::ARG_RETRY_OPTIONS => Workflow::getCurrentContext()->getInfo()->retryOptions,
};
}
}

#[WorkflowInterface]
class ChildWorkflow
{
#[WorkflowMethod('Extra_Workflow_WorkflowInfo_Child')]
public function run()
{
return yield Workflow::newChildWorkflowStub(ChildWorkflow2::class)->run();
}
}

#[WorkflowInterface]
class ChildWorkflow2
{
#[WorkflowMethod('Extra_Workflow_WorkflowInfo_Child2')]
public function run()
{
return Workflow::getCurrentContext()->getInfo()->rootExecution;
}
}
20 changes: 4 additions & 16 deletions tests/Unit/DTO/Type/ArrayType/ArrayTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,11 @@ public function testUnmarshalling(): void

public function testSetNullToNotNullable(): void
{
try {
$this->unmarshal([
'foo' => null,
], new ArrayDto());
$dto = $this->unmarshal([
'foo' => null,
], new ArrayDto());

$this->fail('Null value should not be allowed.');
} catch (\Throwable $e) {
$this->assertStringContainsString(
'`foo`',
$e->getMessage(),
);
$this->assertInstanceOf(\InvalidArgumentException::class, $e->getPrevious());
$this->assertStringContainsString(
'Passed value must be a type of array, but null given',
$e->getPrevious()->getMessage(),
);
}
self::assertSame([], $dto->foo);
}

protected function getTypeMatchers(): array
Expand Down
1 change: 1 addition & 0 deletions tests/Unit/DTO/WorkflowInfoTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public function testMarshalling(): void
'Priority' => [
'priority_key' => 0,
],
'RetryPolicy' => null,
];

$this->assertSame($expected, $this->marshal($dto));
Expand Down
Loading