Skip to content

Commit 68646e0

Browse files
committed
feat: support raw value
1 parent c8b5825 commit 68646e0

File tree

8 files changed

+232
-1
lines changed

8 files changed

+232
-1
lines changed

src/DataConverter/DataConverter.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public static function createDefault(): DataConverterInterface
3333
return new DataConverter(
3434
new NullConverter(),
3535
new BinaryConverter(),
36+
new RawValueConverter(),
3637
new ProtoJsonConverter(),
3738
new ProtoConverter(),
3839
new JsonConverter(),
@@ -47,7 +48,7 @@ public function fromPayload(Payload $payload, $type)
4748
$encoding = $meta[EncodingKeys::METADATA_ENCODING_KEY];
4849

4950
if (!isset($this->converters[$encoding])) {
50-
throw new DataConverterException(\sprintf('Undefined payload encoding %s', $encoding));
51+
throw new DataConverterException(\sprintf('Undefined payload encoding "%s"', $encoding));
5152
}
5253

5354
$type = Type::create($type);

src/DataConverter/EncodingKeys.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ final class EncodingKeys
1717
public const METADATA_MESSAGE_TYPE = 'messageType';
1818
public const METADATA_ENCODING_NULL = 'binary/null';
1919
public const METADATA_ENCODING_RAW = 'binary/plain';
20+
public const METADATA_ENCODING_RAW_VALUE = 'binary';
2021
public const METADATA_ENCODING_JSON = 'json/plain';
2122
public const METADATA_ENCODING_PROTOBUF_JSON = 'json/protobuf';
2223
public const METADATA_ENCODING_PROTOBUF = 'binary/protobuf';

src/DataConverter/RawValue.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/**
4+
* This file is part of Temporal package.
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
declare(strict_types=1);
11+
12+
namespace Temporal\DataConverter;
13+
14+
use Temporal\Api\Common\V1\Payload;
15+
16+
final class RawValue
17+
{
18+
private Payload $payload;
19+
20+
public function __construct(Payload $data)
21+
{
22+
$this->payload = $data;
23+
}
24+
25+
public function getPayload(): Payload
26+
{
27+
return $this->payload;
28+
}
29+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/**
4+
* This file is part of Temporal package.
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
declare(strict_types=1);
11+
12+
namespace Temporal\DataConverter;
13+
14+
use Temporal\Api\Common\V1\Payload;
15+
use Temporal\Exception\DataConverterException;
16+
17+
class RawValueConverter extends Converter
18+
{
19+
public function getEncodingType(): string
20+
{
21+
return EncodingKeys::METADATA_ENCODING_RAW_VALUE;
22+
}
23+
24+
public function toPayload($value): ?Payload
25+
{
26+
if (!$value instanceof RawValue) {
27+
return null;
28+
}
29+
30+
$payload = $value->getPayload();
31+
$payload->setMetadata([EncodingKeys::METADATA_ENCODING_KEY => EncodingKeys::METADATA_ENCODING_RAW_VALUE]);
32+
33+
return $payload;
34+
}
35+
36+
public function fromPayload(Payload $payload, Type $type): RawValue
37+
{
38+
if (!$type->isClass() || $type->getName() !== RawValue::class) {
39+
throw new DataConverterException(\sprintf('Unable to convert raw data to non %s type', RawValue::class));
40+
}
41+
42+
return new RawValue($payload);
43+
}
44+
}

tests/Acceptance/App/Feature/ClientFactory.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Temporal\Tests\Acceptance\App\Feature;
66

7+
use Temporal\DataConverter\RawValueConverter;
78
use Temporal\Tests\Acceptance\App\Attribute\Client;
89
use Temporal\Tests\Acceptance\App\Runtime\State;
910
use Psr\Container\ContainerInterface;
@@ -52,6 +53,7 @@ public function workflowClient(\ReflectionParameter $context): WorkflowClientInt
5253
if ($attribute->payloadConverters !== []) {
5354
$converters = [
5455
new NullConverter(),
56+
new RawValueConverter(),
5557
new BinaryConverter(),
5658
new ProtoConverter(),
5759
new ProtoJsonConverter(),
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Temporal\Tests\Acceptance\Harness\DataConverter\RawValue;
6+
7+
use PHPUnit\Framework\Attributes\Test;
8+
use Temporal\Api\Common\V1\Payload;
9+
use Temporal\Api\Workflowservice\V1\StartWorkflowExecutionRequest;
10+
use Temporal\Client\GRPC\ContextInterface;
11+
use Temporal\Client\WorkflowStubInterface;
12+
use Temporal\DataConverter\EncodedValues;
13+
use Temporal\DataConverter\EncodingKeys;
14+
use Temporal\DataConverter\RawValue;
15+
use Temporal\Interceptor\GrpcClientInterceptor;
16+
use Temporal\Interceptor\PipelineProvider;
17+
use Temporal\Interceptor\SimplePipelineProvider;
18+
use Temporal\Interceptor\Trait\WorkflowClientCallsInterceptorTrait;
19+
use Temporal\Interceptor\WorkflowClient\GetResultInput;
20+
use Temporal\Interceptor\WorkflowClientCallsInterceptor;
21+
use Temporal\Tests\Acceptance\App\Attribute\Client;
22+
use Temporal\Tests\Acceptance\App\Attribute\Stub;
23+
use Temporal\Tests\Acceptance\App\TestCase;
24+
use Temporal\Workflow\WorkflowInterface;
25+
use Temporal\Workflow\WorkflowMethod;
26+
27+
class RawValueTest extends TestCase
28+
{
29+
private Interceptor $interceptor;
30+
31+
public function pipelineProvider(): PipelineProvider
32+
{
33+
return new SimplePipelineProvider([$this->interceptor]);
34+
}
35+
36+
#[Test]
37+
public function check(
38+
#[Stub('Harness_DataConverter_RawValue')]
39+
#[Client(pipelineProvider: [self::class, 'pipelineProvider'])]
40+
WorkflowStubInterface $stub,
41+
): void {
42+
$result = $stub->getResult(RawValue::class);
43+
44+
self::assertInstanceOf(RawValue::class, $result);
45+
self::assertInstanceOf(Payload::class, $result->getPayload());
46+
self::assertSame('hello world', $result->getPayload()->getData());
47+
48+
# Check arguments
49+
self::assertNotNull($this->interceptor->startRequest);
50+
self::assertNotNull($this->interceptor->result);
51+
52+
/** @var Payload $payload */
53+
$payload = $this->interceptor->startRequest->getInput()?->getPayloads()[0] ?? null;
54+
self::assertNotNull($payload);
55+
56+
self::assertSame(EncodingKeys::METADATA_ENCODING_RAW_VALUE, $payload->getMetadata()['encoding']);
57+
58+
// Check result value from interceptor
59+
/** @var Payload $resultPayload */
60+
$resultPayload = $this->interceptor->result->toPayloads()->getPayloads()[0];
61+
self::assertSame(EncodingKeys::METADATA_ENCODING_RAW_VALUE, $resultPayload->getMetadata()['encoding']);
62+
}
63+
64+
protected function setUp(): void
65+
{
66+
$this->interceptor = new Interceptor();
67+
parent::setUp();
68+
}
69+
}
70+
71+
#[WorkflowInterface]
72+
class FeatureWorkflow
73+
{
74+
#[WorkflowMethod('Harness_DataConverter_RawValue')]
75+
public function run()
76+
{
77+
return yield new RawValue(new Payload(['data' => 'hello world']));
78+
}
79+
}
80+
81+
class Interceptor implements GrpcClientInterceptor, WorkflowClientCallsInterceptor
82+
{
83+
use WorkflowClientCallsInterceptorTrait;
84+
85+
public ?StartWorkflowExecutionRequest $startRequest = null;
86+
public ?EncodedValues $result = null;
87+
88+
public function interceptCall(string $method, object $arg, ContextInterface $ctx, callable $next): object
89+
{
90+
$arg instanceof StartWorkflowExecutionRequest and $this->startRequest = $arg;
91+
return $next($method, $arg, $ctx);
92+
}
93+
94+
public function getResult(GetResultInput $input, callable $next): ?EncodedValues
95+
{
96+
return $this->result = $next($input);
97+
}
98+
}

tests/Acceptance/worker.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Temporal\DataConverter\NullConverter;
2222
use Temporal\DataConverter\ProtoConverter;
2323
use Temporal\DataConverter\ProtoJsonConverter;
24+
use Temporal\DataConverter\RawValueConverter;
2425
use Temporal\Internal\Support\StackRenderer;
2526
use Temporal\Testing\Command;
2627
use Temporal\Tests\Acceptance\App\Runtime\Feature;
@@ -52,6 +53,7 @@
5253
$converters = [
5354
new NullConverter(),
5455
new BinaryConverter(),
56+
new RawValueConverter(),
5557
new ProtoJsonConverter(),
5658
new ProtoConverter(),
5759
new JsonConverter(),
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
/**
4+
* This file is part of Temporal package.
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
declare(strict_types=1);
11+
12+
namespace Unit\DataConverter;
13+
14+
use Temporal\Api\Common\V1\Payload;
15+
use Temporal\DataConverter\DataConverter;
16+
use Temporal\DataConverter\DataConverterInterface;
17+
use Temporal\DataConverter\EncodingKeys;
18+
use Temporal\DataConverter\RawValue;
19+
use Temporal\Tests\Unit\AbstractUnit;
20+
21+
/**
22+
* @group unit
23+
* @group data-converter
24+
*/
25+
class RawValueConverterTest extends AbstractUnit
26+
{
27+
public function testRawPayloadEncoding(): void
28+
{
29+
$innerPayload = new Payload(['data' => 1]);
30+
$message = new RawValue($innerPayload);
31+
32+
$payload = DataConverter::createDefault()->toPayload($message);
33+
34+
self::assertSame($innerPayload, $payload);
35+
self::assertSame(EncodingKeys::METADATA_ENCODING_RAW_VALUE, $payload->getMetadata()[EncodingKeys::METADATA_ENCODING_KEY]);
36+
}
37+
38+
public function testRawPayloadDecoding(): void
39+
{
40+
$innerPayload = new Payload(['data' => 1]);
41+
$message = new RawValue($innerPayload);
42+
43+
$encoded = DataConverter::createDefault()->toPayload($message);
44+
$decoded = DataConverter::createDefault()->fromPayload($encoded, RawValue::class);
45+
46+
self::assertInstanceOf(RawValue::class, $decoded);
47+
self::assertSame($decoded->getPayload(), $encoded);
48+
}
49+
50+
protected function create(): DataConverterInterface
51+
{
52+
return DataConverter::createDefault();
53+
}
54+
}

0 commit comments

Comments
 (0)