From e11306c3f8e929a53a557c6da91996cfd751df54 Mon Sep 17 00:00:00 2001 From: Aleksei Gagarin Date: Mon, 10 Feb 2025 20:40:02 +0400 Subject: [PATCH] Fix unmarshalling of ScheduleSpec with null jitter (#563) * Fix unmarshalling of ScheduleSpec with null jitter Search attributes command: force objects in JSON * Add tests --- src/Internal/Marshaller/Type/DurationJsonType.php | 8 ++++++-- .../Transport/Request/UpsertSearchAttributes.php | 2 +- .../Request/UpsertTypedSearchAttributes.php | 2 +- .../DurationJsonType/DurationJsonTestCase.php | 15 ++++++++++++++- .../DurationJsonType/Stub/DurationJsonDto.php | 6 ++++++ 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/Internal/Marshaller/Type/DurationJsonType.php b/src/Internal/Marshaller/Type/DurationJsonType.php index 67e895e7a..87b607807 100644 --- a/src/Internal/Marshaller/Type/DurationJsonType.php +++ b/src/Internal/Marshaller/Type/DurationJsonType.php @@ -76,8 +76,12 @@ public function parse($value, $current): CarbonInterval { if (\is_array($value) && isset($value['seconds']) && isset($value['nanos'])) { // The highest precision is milliseconds either way. - $value = $value['seconds'] * 1_000_000_000 + $value['nanos']; - return DateInterval::parse($value, DateInterval::FORMAT_NANOSECONDS); + $value = $value['seconds'] * 1_000_000 + (int) \round($value['nanos'] / 1000); + return DateInterval::parse($value, DateInterval::FORMAT_MICROSECONDS); + } + + if ($value === null) { + return CarbonInterval::create(); } return DateInterval::parse($value, $this->fallbackFormat); diff --git a/src/Internal/Transport/Request/UpsertSearchAttributes.php b/src/Internal/Transport/Request/UpsertSearchAttributes.php index b704f4ce8..257bd8028 100644 --- a/src/Internal/Transport/Request/UpsertSearchAttributes.php +++ b/src/Internal/Transport/Request/UpsertSearchAttributes.php @@ -16,7 +16,7 @@ final class UpsertSearchAttributes extends Request public function __construct( private readonly array $searchAttributes, ) { - parent::__construct(self::NAME, ['searchAttributes' => $searchAttributes]); + parent::__construct(self::NAME, ['searchAttributes' => (object) $searchAttributes]); } /** diff --git a/src/Internal/Transport/Request/UpsertTypedSearchAttributes.php b/src/Internal/Transport/Request/UpsertTypedSearchAttributes.php index 651910fa3..e3c0c0f8f 100644 --- a/src/Internal/Transport/Request/UpsertTypedSearchAttributes.php +++ b/src/Internal/Transport/Request/UpsertTypedSearchAttributes.php @@ -18,7 +18,7 @@ final class UpsertTypedSearchAttributes extends Request public function __construct( private readonly array $searchAttributes, ) { - parent::__construct(self::NAME, ['search_attributes' => $this->prepareSearchAttributes()]); + parent::__construct(self::NAME, ['search_attributes' => (object) $this->prepareSearchAttributes()]); } /** diff --git a/tests/Unit/DTO/Type/DurationJsonType/DurationJsonTestCase.php b/tests/Unit/DTO/Type/DurationJsonType/DurationJsonTestCase.php index fa89fdc04..7305b9f2d 100644 --- a/tests/Unit/DTO/Type/DurationJsonType/DurationJsonTestCase.php +++ b/tests/Unit/DTO/Type/DurationJsonType/DurationJsonTestCase.php @@ -21,12 +21,25 @@ class DurationJsonTestCase extends AbstractDTOMarshalling public function testMarshalAndUnmarshalDuration(): void { $dto = new DurationJsonDto(); - $dto->duration = DateInterval::parse(1); + $dto->duration = DateInterval::parse(100); + $dto->durationProto = DateInterval::parse(12000); $result = $this->marshal($dto); $unmarshal = $this->unmarshal($result, new DurationJsonDto()); self::assertInstanceOf(\DateInterval::class, $unmarshal->duration); + self::assertInstanceOf(\DateInterval::class, $unmarshal->durationProto); + self::assertSame('0 100000', $unmarshal->duration->format('%s %f')); + self::assertSame('12 0', $unmarshal->durationProto->format('%s %f')); + } + + public function testUnmarshallEmptyDuration(): void + { + $result = ['duration' => null, 'duration_proto' => null]; + $unmarshal = $this->unmarshal($result, new DurationJsonDto()); + + self::assertSame('0.0', $unmarshal->duration->format('%s.%f')); + self::assertSame('0.0', $unmarshal->durationProto->format('%s.%f')); } protected function getTypeMatchers(): array diff --git a/tests/Unit/DTO/Type/DurationJsonType/Stub/DurationJsonDto.php b/tests/Unit/DTO/Type/DurationJsonType/Stub/DurationJsonDto.php index 76008ce36..cebab8b33 100644 --- a/tests/Unit/DTO/Type/DurationJsonType/Stub/DurationJsonDto.php +++ b/tests/Unit/DTO/Type/DurationJsonType/Stub/DurationJsonDto.php @@ -11,7 +11,13 @@ namespace Temporal\Tests\Unit\DTO\Type\DurationJsonType\Stub; +use Google\Protobuf\Duration; +use Temporal\Internal\Marshaller\Meta\Marshal; + class DurationJsonDto { public \DateInterval $duration; + + #[Marshal('duration_proto', of: Duration::class)] + public \DateInterval $durationProto; }