Skip to content
Open
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
15 changes: 10 additions & 5 deletions src/Client/Schedule/Policy/SchedulePolicies.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Google\Protobuf\Duration;
use Temporal\Internal\Marshaller\Meta\Marshal;
use Temporal\Internal\Marshaller\Type\DateIntervalType;
use Temporal\Internal\Support\DateInterval;
use Temporal\Internal\Traits\CloneWith;

Expand Down Expand Up @@ -34,10 +35,12 @@ final class SchedulePolicies
* If the Temporal server misses an action due to one or more components
* being down, and comes back up, the action will be run if the scheduled
* time is within this window from the current time.
* This value defaults to 60 seconds, and can't be less than 10 seconds.
* When unset, this value is omitted so the Temporal Server applies its
* default (currently one year). An explicitly set value can't be less than
* 10 seconds.
*/
#[Marshal(name: 'catchup_window', of: Duration::class)]
public readonly \DateInterval $catchupWindow;
#[Marshal(name: 'catchup_window', type: DateIntervalType::class, of: Duration::class, nullable: true)]
public readonly ?\DateInterval $catchupWindow;

/**
* If true, and a Workflow run fails or times out, pause the Schedule.
Expand All @@ -50,7 +53,7 @@ final class SchedulePolicies
private function __construct()
{
$this->overlapPolicy = ScheduleOverlapPolicy::Unspecified;
$this->catchupWindow = new \DateInterval('PT60S');
$this->catchupWindow = null;
$this->pauseOnFailure = false;
}

Expand All @@ -75,7 +78,9 @@ public function withOverlapPolicy(ScheduleOverlapPolicy $overlapPolicy): self
* If the Temporal server misses an action due to one or more components
* being down, and comes back up, the action will be run if the scheduled
* time is within this window from the current time.
* This value defaults to 60 seconds, and can't be less than 10 seconds.
* When unset, this value is omitted so the Temporal Server applies its
* default (currently one year). An explicitly set value can't be less than
* 10 seconds.
*
* @param DateIntervalValue $interval
*/
Expand Down
2 changes: 1 addition & 1 deletion src/Internal/Mapper/ScheduleMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function toMessage(Schedule $dto): \Temporal\Api\Schedule\V1\Schedule
$array = $this->marshaller->marshal($dto);
$array['policies']['overlap_policy'] = $dto->policies->overlapPolicy->value;

$array['policies'] = new SchedulePolicies($array['policies'] ?? []);
$array['policies'] = new SchedulePolicies(self::cleanArray($array['policies'] ?? []));
$array['spec'] = $this->prepareSpec($array['spec'] ?? []);
$array['state'] = new ScheduleState($array['state'] ?? []);
isset($array['action']) and $array['action'] = $this->prepareAction($dto->action, $array['action']);
Expand Down
13 changes: 5 additions & 8 deletions src/Internal/Marshaller/ProtoToArrayConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,11 @@ private function getMapper(Message $message): \Closure
'U.u',
\sprintf('%d.%d', $input->getSeconds(), $input->getNanos() / 1000),
),
Duration::class => static function (Duration $input): \DateInterval {
$now = new \DateTimeImmutable('@0');
return $now->diff(
$now->modify(
\sprintf('+%d seconds +%d microseconds', $input->getSeconds(), $input->getNanos() / 1000),
),
);
},
Duration::class => static fn(Duration $input): \DateInterval =>
\Temporal\Internal\Support\DateInterval::parse(
(int) $input->getSeconds() * 1_000_000 + \intdiv($input->getNanos(), 1_000),
\Temporal\Internal\Support\DateInterval::FORMAT_MICROSECONDS,
),
SearchAttributes::class => fn(SearchAttributes $input): EncodedCollection =>
EncodedCollection::fromPayloadCollection(
$input->getIndexedFields(),
Expand Down
7 changes: 7 additions & 0 deletions tests/Acceptance/Harness/Schedule/BasicTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Temporal\Client\Schedule\Spec\ScheduleSpec;
use Temporal\Client\ScheduleClientInterface;
use Temporal\Client\WorkflowClientInterface;
use Temporal\Internal\Support\DateInterval;
use Temporal\Tests\Acceptance\App\Runtime\Feature;
use Temporal\Tests\Acceptance\App\Runtime\State;
use Temporal\Tests\Acceptance\App\TestCase;
Expand Down Expand Up @@ -65,6 +66,12 @@ public static function check(
$action = $description->schedule->action;
self::assertInstanceOf(StartWorkflowAction::class, $action);
self::assertSame($workflowId, $action->workflowId);
$catchupWindow = $description->schedule->policies->catchupWindow;
self::assertNotNull($catchupWindow);
self::assertSame(
365 * 24 * 60 * 60,
(int) DateInterval::parse($catchupWindow)->totalSeconds,
);

// Confirm simple list
$found = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace Temporal\Tests\Unit\Internal\Marshaller;

use Google\Protobuf\Duration;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
use Temporal\DataConverter\DataConverter;
use Temporal\Internal\Marshaller\ProtoToArrayConverter;
use Temporal\Internal\Support\DateInterval;

#[CoversClass(ProtoToArrayConverter::class)]
final class ProtoToArrayConverterTestCase extends TestCase
{
public function testDurationPreservesExactSeconds(): void
{
$converter = new ProtoToArrayConverter(DataConverter::createDefault());

$interval = $converter->convert(
(new Duration())->setSeconds(365 * 24 * 60 * 60),
);

self::assertInstanceOf(\DateInterval::class, $interval);
self::assertSame(
365 * 24 * 60 * 60,
(int) DateInterval::parse($interval)->totalSeconds,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ public function testToMessageEmptyValues(): void
$this->assertEmpty($spec->getTimezoneName());

// Test Policies
$this->assertEquals(60, $policies->getCatchupWindow()->getSeconds());
$this->assertNull($policies->getCatchupWindow());
$this->assertFalse($policies->getPauseOnFailure());
$this->assertEquals(ScheduleOverlapPolicy::SCHEDULE_OVERLAP_POLICY_UNSPECIFIED, $policies->getOverlapPolicy());

Expand Down