Skip to content

Commit

Permalink
Add memo test
Browse files Browse the repository at this point in the history
Fix internal issues
Workflow::info's memo is now converted to values array
  • Loading branch information
roxblnfk committed Feb 6, 2025
1 parent 3d50065 commit d39922e
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/Internal/Transport/Request/UpsertMemo.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ final class UpsertMemo extends Request
public function __construct(
private readonly array $memo,
) {
parent::__construct(self::NAME, ['memo' => $memo]);
parent::__construct(self::NAME, ['memo' => (object) $memo]);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Internal/Transport/Request/UpsertSearchAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()]);
}

/**
Expand Down
29 changes: 29 additions & 0 deletions src/Internal/Transport/Router/StartWorkflow.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Temporal\Internal\Transport\Router;

use React\Promise\Deferred;
use Temporal\Api\Common\V1\Memo;
use Temporal\Api\Common\V1\SearchAttributes;
use Temporal\Common\TypedSearchAttributes;
use Temporal\DataConverter\EncodedCollection;
Expand Down Expand Up @@ -58,8 +59,10 @@ public function handle(ServerRequestInterface $request, array $headers, Deferred

// Search Attributes and Typed Search Attributes
$searchAttributes = $this->convertSearchAttributes($options['info']['SearchAttributes'] ?? null);
$memo = $this->convertMemo($options['info']['Memo'] ?? null);
$options['info']['SearchAttributes'] = $searchAttributes?->getValues();
$options['info']['TypedSearchAttributes'] = $this->prepareTypedSA($options['search_attributes'] ?? null);
$options['info']['Memo'] = $memo?->getValues();

/** @var Input $input */
$input = $this->services->marshaller->unmarshal($options, new Input());
Expand Down Expand Up @@ -156,6 +159,32 @@ private function convertSearchAttributes(?array $param): ?EncodedCollection
}
}

private function convertMemo(?array $param): ?EncodedCollection
{
if (!\is_array($param)) {
return null;
}

if ($param === []) {
return EncodedCollection::empty();
}

try {
$memo = (new Memo());
$memo->mergeFromJsonString(
\json_encode($param),

Check failure on line 175 in src/Internal/Transport/Router/StartWorkflow.php

View workflow job for this annotation

GitHub Actions / Psalm Validation (PHP 8.3, OS ubuntu-latest)

PossiblyFalseArgument

src/Internal/Transport/Router/StartWorkflow.php:175:17: PossiblyFalseArgument: Argument 1 of Temporal\Api\Common\V1\Memo::mergeFromJsonString cannot be false, possibly string value expected (see https://psalm.dev/104)

Check failure on line 175 in src/Internal/Transport/Router/StartWorkflow.php

View workflow job for this annotation

GitHub Actions / Psalm Validation (PHP 8.3, OS ubuntu-latest)

PossiblyFalseArgument

src/Internal/Transport/Router/StartWorkflow.php:175:17: PossiblyFalseArgument: Argument 1 of Temporal\Api\Common\V1\Memo::mergeFromJsonString cannot be false, possibly string value expected (see https://psalm.dev/104)
true,
);

return EncodedCollection::fromPayloadCollection(
$memo->getFields(),
$this->services->dataConverter,
);
} catch (\Throwable) {
return null;
}
}

private function prepareTypedSA(?array $param): TypedSearchAttributes
{
return $param === null
Expand Down
12 changes: 12 additions & 0 deletions src/Internal/Workflow/WorkflowContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,10 @@ public function upsertMemo(array $values): void
{
$this->callsInterceptor->with(
function (UpsertMemoInput $input): PromiseInterface {
if ($input->memo === []) {
return resolve();
}

$result = $this->request(new UpsertMemo($input->memo), false);

/** @psalm-suppress UnsupportedPropertyReferenceUsage $memo */
Expand All @@ -479,6 +483,10 @@ public function upsertSearchAttributes(array $searchAttributes): void
{
$this->callsInterceptor->with(
function (UpsertSearchAttributesInput $input): PromiseInterface {
if ($input->searchAttributes === []) {
return resolve();
}

$result = $this->request(new UpsertSearchAttributes($input->searchAttributes), false);

/** @psalm-suppress UnsupportedPropertyReferenceUsage $sa */
Expand All @@ -503,6 +511,10 @@ public function upsertTypedSearchAttributes(SearchAttributeUpdate ...$updates):
{
$this->callsInterceptor->with(
function (UpsertTypedSearchAttributesInput $input): PromiseInterface {
if ($input->updates === []) {
return resolve();
}

$result = $this->request(new UpsertTypedSearchAttributes($input->updates), false);

// Merge changes
Expand Down
2 changes: 1 addition & 1 deletion src/Workflow.php
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@ public static function upsertSearchAttributes(array $searchAttributes): void
*/
public static function upsertTypedSearchAttributes(SearchAttributeUpdate ...$updates): void
{
$updates === [] or self::getCurrentContext()->upsertTypedSearchAttributes(...$updates);
self::getCurrentContext()->upsertTypedSearchAttributes(...$updates);
}

/**
Expand Down
128 changes: 128 additions & 0 deletions tests/Acceptance/Extra/Workflow/MemoTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php

declare(strict_types=1);

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

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

#[CoversFunction('Temporal\Workflow::upsertMemo')]
class MemoTest extends TestCase
{
#[Test]
public function sendEmpty(
#[Stub(
type: 'Extra_Workflow_Memo',
memo: [
'key1' => 'value1',
'key2' => 'value2',
'key3' => ['foo' => 'bar'],
42 => 'value4',
],
)] WorkflowStubInterface $stub,
): void {
try {
$stub->update('setMemo', []);

// Get Search Attributes using Client API
$clientMemo = $stub->describe()->info->memo->getValues();

// Complete workflow
/** @see TestWorkflow::exit */
$stub->signal('exit');
} catch (\Throwable $e) {
$stub->terminate('test failed');
throw $e;
}

// Get Memo from Workflow
$result = $stub->getResult();

$expected = [
'key1' => 'value1',
'key2' => 'value2',
'key3' => (object) ['foo' => 'bar'],
42 => 'value4',
];
$this->assertEquals($expected, $clientMemo);
$this->assertEquals($expected, (array) $result);
}

#[Test]
public function overrideAddAndRemove(
#[Stub(
type: 'Extra_Workflow_Memo',
memo: [
'key1' => 'value1',
'key2' => 'value2',
'key3' => ['foo' => 'bar'],
],
)] WorkflowStubInterface $stub,
): void {
try {
$stub->update('setMemo', [
'key2' => null,
'key3' => 42,
'key4' => 'value4',
]);

// Get Search Attributes using Client API
$clientMemo = $stub->describe()->info->memo->getValues();

// Complete workflow
/** @see TestWorkflow::exit */
$stub->signal('exit');
} catch (\Throwable $e) {
$stub->terminate('test failed');
throw $e;
}

// Get Memo from Workflow
$result = $stub->getResult();

$expected = [
'key1' => 'value1',
'key3' => 42,
'key4' => 'value4',
];
$this->assertEquals($expected, $clientMemo);
$this->assertEquals($expected, (array) $result);
}
}

#[WorkflowInterface]
class TestWorkflow
{
private bool $exit = false;

#[WorkflowMethod(name: "Extra_Workflow_Memo")]
public function handle()
{
yield Workflow::await(
fn(): bool => $this->exit,
);

tr(Workflow::getInfo()->memo);

return Workflow::getInfo()->memo;
}

#[Workflow\UpdateMethod]
public function setMemo(array $memo): void
{
Workflow::upsertMemo($memo);
}

#[Workflow\SignalMethod]
public function exit(): void
{
$this->exit = true;
}
}

0 comments on commit d39922e

Please sign in to comment.