Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SearchAttributes in ChildWorkflow #515

Merged
merged 11 commits into from
Oct 8, 2024
47 changes: 5 additions & 42 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -212,43 +212,14 @@
<code><![CDATA[$name]]></code>
<code><![CDATA[$value]]></code>
</InvalidArgument>
<MismatchingDocblockParamType>
<code><![CDATA[iterable<array-key, Payload>]]></code>
</MismatchingDocblockParamType>
<MismatchingDocblockReturnType>
<code><![CDATA[EncodedCollection]]></code>
</MismatchingDocblockReturnType>
<MoreSpecificImplementedParamType>
<code><![CDATA[$type]]></code>
</MoreSpecificImplementedParamType>
<PossiblyNullReference>
<code><![CDATA[fromPayload]]></code>
</PossiblyNullReference>
<UnsafeInstantiation>
<code><![CDATA[new static()]]></code>
<code><![CDATA[new static()]]></code>
</UnsafeInstantiation>
</file>
<file src="src/DataConverter/EncodedValues.php">
<InvalidNullableReturnType>
<code><![CDATA[array]]></code>
</InvalidNullableReturnType>
<MissingClosureParamType>
<code><![CDATA[$value]]></code>
</MissingClosureParamType>
<NullableReturnStatement>
<code><![CDATA[$result]]></code>
<code><![CDATA[$result]]></code>
</NullableReturnStatement>
<PossiblyNullArrayAccess>
<code><![CDATA[$this->payloads[$index]]]></code>
</PossiblyNullArrayAccess>
<PossiblyNullIterator>
<code><![CDATA[$this->values]]></code>
</PossiblyNullIterator>
<PossiblyNullReference>
<code><![CDATA[$this->payloads]]></code>
</PossiblyNullReference>
<UnsafeInstantiation>
<code><![CDATA[new static()]]></code>
<code><![CDATA[new static()]]></code>
Expand Down Expand Up @@ -661,6 +632,11 @@
<code><![CDATA[NamedArgumentConstructor]]></code>
</DeprecatedClass>
</file>
<file src="src/Internal/Marshaller/Meta/MarshalAssocArray.php">
<DeprecatedClass>
<code><![CDATA[NamedArgumentConstructor]]></code>
</DeprecatedClass>
</file>
<file src="src/Internal/Marshaller/Meta/MarshalDateTime.php">
<DeprecatedClass>
<code><![CDATA[NamedArgumentConstructor]]></code>
Expand Down Expand Up @@ -694,12 +670,6 @@
<InvalidFalsableReturnType>
<code><![CDATA[\DateTimeImmutable]]></code>
</InvalidFalsableReturnType>
<InvalidReturnStatement>
<code><![CDATA[\Temporal\Interceptor\Header::fromPayloadCollection($input->getFields(), $this->converter)]]></code>
</InvalidReturnStatement>
<InvalidReturnType>
<code><![CDATA[HeaderInterface]]></code>
</InvalidReturnType>
<LessSpecificReturnStatement>
<code><![CDATA[$mapper]]></code>
</LessSpecificReturnStatement>
Expand Down Expand Up @@ -779,7 +749,6 @@
</InvalidReturnStatement>
<InvalidReturnType>
<code><![CDATA[?string]]></code>
<code><![CDATA[iterable<class-string<DetectableTypeInterface>>]]></code>
</InvalidReturnType>
<LessSpecificReturnStatement>
<code><![CDATA[$result]]></code>
Expand Down Expand Up @@ -1306,9 +1275,6 @@
</PossiblyInvalidArgument>
</file>
<file src="src/Worker/Transport/Codec/JsonCodec/Decoder.php">
<InvalidArgument>
<code><![CDATA[Header::fromPayloadCollection($headers->getFields(), $this->dataConverter)]]></code>
</InvalidArgument>
<InvalidReturnStatement>
<code><![CDATA[match (true) {
isset($command['command']) => $this->parseRequest($command, $info),
Expand Down Expand Up @@ -1344,9 +1310,6 @@
<ArgumentTypeCoercion>
<code><![CDATA[$msg->getCommand()]]></code>
</ArgumentTypeCoercion>
<InvalidArgument>
<code><![CDATA[$header]]></code>
</InvalidArgument>
<PossiblyNullArgument>
<code><![CDATA[$msg->getFailure()]]></code>
<code><![CDATA[$msg->getPayloads()]]></code>
Expand Down
44 changes: 15 additions & 29 deletions src/DataConverter/EncodedCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,16 @@

namespace Temporal\DataConverter;

use ArrayAccess;
use Countable;
use IteratorAggregate;
use Temporal\Api\Common\V1\Payload;
use Traversable;

/**
* @psalm-type TPayloadsCollection = Traversable&ArrayAccess&Countable
* Assoc collection of typed values.
*
* @psalm-type TKey = array-key
* @psalm-type TValue = mixed
* @psalm-type TPayloadsCollection = \Traversable&\ArrayAccess<TKey, TValue>&\Countable
*
* @implements IteratorAggregate<TKey, TValue>
* @implements \IteratorAggregate<TKey, TValue>
*/
class EncodedCollection implements \IteratorAggregate, \Countable
{
Expand All @@ -36,16 +34,14 @@ class EncodedCollection implements \IteratorAggregate, \Countable
*/
private ?\ArrayAccess $payloads = null;

/** @var array<TKey, TValue> */
private array $values = [];

/**
* Cannot be constructed directly.
*/
private function __construct() {}
final private function __construct() {}

/**
* @return static
*/
public static function empty(): static
{
$ev = new static();
Expand All @@ -55,10 +51,7 @@ public static function empty(): static
}

/**
* @param iterable $values
* @param DataConverterInterface|null $dataConverter
*
* @return static
* @param iterable<TKey, TValue> $values
*/
public static function fromValues(iterable $values, ?DataConverterInterface $dataConverter = null): static
{
Expand All @@ -72,10 +65,7 @@ public static function fromValues(iterable $values, ?DataConverterInterface $dat
}

/**
* @param iterable<array-key, Payload> $payloads
* @param DataConverterInterface $dataConverter
*
* @return EncodedCollection
* @param array<TKey, Payload>|TPayloadsCollection $payloads
*/
public static function fromPayloadCollection(
array|\ArrayAccess $payloads,
Expand Down Expand Up @@ -103,8 +93,6 @@ public function isEmpty(): bool
/**
* @param array-key $name
* @param Type|string|null $type
*
* @return mixed
*/
public function getValue(int|string $name, mixed $type = null): mixed
{
Expand Down Expand Up @@ -143,9 +131,8 @@ public function getValues(): array
public function getIterator(): \Traversable
{
yield from $this->values;
if ($this->payloads !== null) {
$this->converter !== null or $this->payloads->count() === 0
or throw new \LogicException('DataConverter is not set.');
if ($this->payloads !== null && $this->payloads->count() > 0) {
$this->converter === null and throw new \LogicException('DataConverter is not set.');

foreach ($this->payloads as $key => $payload) {
yield $key => $this->converter->fromPayload($payload, null);
Expand All @@ -166,9 +153,7 @@ public function toPayloadArray(): array
return $data;
}

if ($this->converter === null) {
throw new \LogicException('DataConverter is not set.');
}
$this->converter === null and throw new \LogicException('DataConverter is not set.');

foreach ($this->values as $key => $value) {
$data[$key] = $this->converter->toPayload($value);
Expand All @@ -177,6 +162,10 @@ public function toPayloadArray(): array
return $data;
}

/**
* @param TKey $name
* @param TValue $value
*/
public function withValue(int|string $name, mixed $value): static
{
$clone = clone $this;
Expand All @@ -193,9 +182,6 @@ public function withValue(int|string $name, mixed $value): static
return $clone;
}

/**
* @param DataConverterInterface $converter
*/
public function setDataConverter(DataConverterInterface $converter): void
{
$this->converter = $converter;
Expand Down
22 changes: 14 additions & 8 deletions src/DataConverter/EncodedValues.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
use Traversable;

/**
* List of typed values.
*
* @psalm-type TPayloadsCollection = Traversable&ArrayAccess&Countable
* @psalm-type TKey = array-key
* @psalm-type TKey = int
* @psalm-type TValue = string
*/
class EncodedValues implements ValuesInterface
Expand Down Expand Up @@ -100,7 +102,7 @@ public static function sliceValues(
public static function decodePromise(PromiseInterface $promise, $type = null): PromiseInterface
{
return $promise->then(
static function ($value) use ($type) {
static function (mixed $value) use ($type) {
if (!$value instanceof ValuesInterface || $value instanceof \Throwable) {
return $value;
}
Expand Down Expand Up @@ -153,22 +155,26 @@ public function getValue(int|string $index, $type = null): mixed
return $this->values[$index];
}

$count = $this->count();
// External SDKs might return an empty array with metadata, alias to null
// Most likely this is a void type
if ($index === 0 && $this->count() === 0 && $this->isVoidType($type)) {
if ($index === 0 && $count === 0 && $this->isVoidType($type)) {
return null;
}

if ($this->converter === null) {
throw new \LogicException('DataConverter is not set');
}
$count > $index or throw new \OutOfBoundsException("Index {$index} is out of bounds.");
$this->converter === null and throw new \LogicException('DataConverter is not set.');

return $this->converter->fromPayload($this->payloads[$index], $type);
\assert($this->payloads !== null);
return $this->converter->fromPayload(
$this->payloads[$index],
$type,
);
}

public function getValues(): array
{
$result = $this->values;
$result = (array) $this->values;

if (empty($this->payloads)) {
return $result;
Expand Down
8 changes: 4 additions & 4 deletions src/Internal/Declaration/Dispatcher/AutowiredPayloads.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ class AutowiredPayloads extends Dispatcher
public function dispatchValues(object $ctx, ValuesInterface $values): mixed
{
$arguments = [];
for ($i = 0; $i < $values->count(); $i++) {
try {
try {
for ($i = 0, $count = $values->count(); $i < $count; $i++) {
$arguments[] = $values->getValue($i, $this->getArgumentTypes()[$i] ?? null);
} catch (\Throwable $e) {
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
}
} catch (\Throwable $e) {
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
}

try {
Expand Down
5 changes: 2 additions & 3 deletions src/Internal/Declaration/Graph/ClassNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@

namespace Temporal\Internal\Declaration\Graph;

use Temporal\Tests\Workflow\Inheritance\ExtendingWorkflow;

final class ClassNode implements NodeInterface
{
/**
Expand All @@ -39,7 +37,8 @@ public function getReflection(): \ReflectionClass
*
* @throws \ReflectionException
*/
public function getAllMethods(): array {
public function getAllMethods(): array
{
/** @var array<non-empty-string, \ReflectionMethod> $result */
$result = [];

Expand Down
41 changes: 41 additions & 0 deletions src/Internal/Marshaller/Meta/MarshalAssocArray.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

/**
* This file is part of Temporal package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Temporal\Internal\Marshaller\Meta;

use Spiral\Attributes\NamedArgumentConstructor;
use Temporal\Internal\Marshaller\Type\AssocArrayType;

/**
* The same as {@see MarshalArray}, but it forces the marshaller to treat the property as an associative array.
* Useful when you send an empty array, but the recipient can't handle it because expects an object,
* but PHP's {@see json_encode()} encodes an empty array as a list `[]` instead of an object `{}`.
*
* @Annotation
* @NamedArgumentConstructor
* @Target({ "PROPERTY", "METHOD" })
*/
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::IS_REPEATABLE), NamedArgumentConstructor]
final class MarshalAssocArray extends Marshal
{
/**
* @param string|null $name
* @param Marshal|string|null $of
* @param bool $nullable
*/
public function __construct(
string $name = null,
Marshal|string|null $of = null,
bool $nullable = true,
) {
parent::__construct($name, AssocArrayType::class, $of, $nullable);
}
}
Loading