<?php
/**
* Temporal Bundle
*
* @author Vlad Shashkov <v.shashkov@pos-credit.ru>
* @copyright Copyright (c) 2023, The Vanta
*/
declare(strict_types=1);
namespace Vanta\Integration\Symfony\Temporal\DataConverter;
use App\ClientVerification\Workflow\Join\BRequest;
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer as ObjectNormalizer;
use Symfony\Component\Serializer\SerializerInterface as Serializer;
use Temporal\Api\Common\V1\Payload;
use Temporal\DataConverter\EncodingKeys;
use Temporal\DataConverter\JsonConverter;
use Temporal\DataConverter\PayloadConverterInterface as PayloadConverter;
use Temporal\DataConverter\Type;
use Temporal\Exception\DataConverterException;
use Throwable;
final readonly class SymfonySerializerDataConverter implements PayloadConverter
{
private const INPUT_TYPE = 'symfony.serializer.type';
public function __construct(
private Serializer $serializer,
private PayloadConverter $payloadConverter = new JsonConverter(),
) {
}
public function getEncodingType(): string
{
return EncodingKeys::METADATA_ENCODING_JSON;
}
public function toPayload($value): Payload
{
$metadata = [
EncodingKeys::METADATA_ENCODING_KEY => $this->getEncodingType(),
];
$context = [ObjectNormalizer::PRESERVE_EMPTY_OBJECTS => true];
if (is_object($value)) {
$metadata[self::INPUT_TYPE] = $value::class;
}
try {
$data = $this->serializer->serialize($value, 'json', $context);
} catch (Throwable $e) {
throw new DataConverterException($e->getMessage(), $e->getCode(), $e);
}
$payload = new Payload();
$payload->setMetadata($metadata);
$payload->setData($data);
return $payload;
}
public function fromPayload(Payload $payload, Type $type): mixed
{
if ("null" == $payload->getData() && $type->allowsNull()) {
return null;
}
/** @var string|null $inputType */
$inputType = $payload->getMetadata()[self::INPUT_TYPE] ?? null;
if ($inputType == BRequest::class) {
// dump
throw new DataConverterException('BAM', 3, null);
}
if (!$type->isClass() && $inputType == null) {
return $this->payloadConverter->fromPayload($payload, $type);
}
try {
return $this->serializer->deserialize($payload->getData(), $inputType ?? $type->getName(), 'json');
} catch (Throwable $e) {
throw new DataConverterException($e->getMessage(), $e->getCode(), $e);
}
}
}
What are you really trying to do?
I am starting the workflow
Describe the bug
If an exception is thrown from PayloadConverter, it cannot be processed and is not visible in the logs or in ui temporal itself. I would like to be able to send this exception to sentry/logs
Minimal Reproduction
ChildWorkflow Case
DataConverter
Temporal UI
Event history
594e549a-bb6d-4d0d-8415-6172ee9e4d56_events.json
ContinueAsNew Case
DataConverter
Temporal UI
Event history
dc5c2461-ab3e-4db6-9b3d-b9975f590159_events.json
ce120686-533e-4f9a-b7fd-c6f164ebf23c_events.json
Environment/Versions