jolicode/elastically

Symfony\Component\ErrorHandler\Exception\FlattenException during scheduleIndex() requests

Daisuke-sama opened this issue · 7 comments

Hi,
I can't figure it out. Please, help. I even started to with clean ElasticaBundle.

[TypeError]
Argument 1 passed to Symfony\Component\ErrorHandler\Exception\FlattenException::setPrevious() must be an instance of Symfony\Component\ErrorHandler\Exception\FlattenException, nul
l given, called in /Users/user/projects/74/doko-deep-search/app/vendor/symfony/property-access/PropertyAccessor.php on line 541

Exception trace:
at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/error-handler/Exception/FlattenException.php:239
Symfony\Component\ErrorHandler\Exception\FlattenException->setPrevious() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/property-access/PropertyAccessor.php:541
Symfony\Component\PropertyAccess\PropertyAccessor->writeProperty() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/property-access/PropertyAccessor.php:138
Symfony\Component\PropertyAccess\PropertyAccessor->setValue() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/serializer/Normalizer/ObjectNormalizer.php:163
Symfony\Component\Serializer\Normalizer\ObjectNormalizer->setAttributeValue() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:336
Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->denormalize() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/serializer/Serializer.php:208
Symfony\Component\Serializer\Serializer->denormalize() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:471
Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->validateAndDenormalize() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:506
Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->denormalizeParameter() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/serializer/Normalizer/AbstractNormalizer.php:385
Symfony\Component\Serializer\Normalizer\AbstractNormalizer->instantiateObject() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:233
Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->instantiateObject() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:311
Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->denormalize() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/serializer/Serializer.php:208
Symfony\Component\Serializer\Serializer->denormalize() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/serializer/Normalizer/ArrayDenormalizer.php:62
Symfony\Component\Serializer\Normalizer\ArrayDenormalizer->denormalize() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/serializer/Serializer.php:208
Symfony\Component\Serializer\Serializer->denormalize() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/serializer/Serializer.php:144
Symfony\Component\Serializer\Serializer->deserialize() at /Users/user/projects/74/doko-deep-search/app/src/Util/IndexJsonSerializer.php:53
App\Util\IndexJsonSerializer->deserialize() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/messenger/Transport/Serialization/Serializer.php:120
Symfony\Component\Messenger\Transport\Serialization\Serializer->decodeStamps() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/messenger/Transport/Serialization/Serializer.php:73
Symfony\Component\Messenger\Transport\Serialization\Serializer->decode() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/doctrine-messenger/Transport/DoctrineReceiver.php:160
Symfony\Component\Messenger\Bridge\Doctrine\Transport\DoctrineReceiver->createEnvelopeFromData() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/doctrine-messenger/Transport/DoctrineReceiver.php:70
Symfony\Component\Messenger\Bridge\Doctrine\Transport\DoctrineReceiver->get() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/doctrine-messenger/Transport/DoctrineTransport.php:45
Symfony\Component\Messenger\Bridge\Doctrine\Transport\DoctrineTransport->get() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/messenger/Worker.php:72
Symfony\Component\Messenger\Worker->run() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/messenger/Command/ConsumeMessagesCommand.php:198
Symfony\Component\Messenger\Command\ConsumeMessagesCommand->execute() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/console/Command/Command.php:256
Symfony\Component\Console\Command\Command->run() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/console/Application.php:989
Symfony\Component\Console\Application->doRunCommand() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/framework-bundle/Console/Application.php:96
Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/console/Application.php:290
Symfony\Component\Console\Application->doRun() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/framework-bundle/Console/Application.php:82
Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /Users/user/projects/74/doko-deep-search/app/vendor/symfony/console/Application.php:166
Symfony\Component\Console\Application->run() at /Users/user/projects/74/doko-deep-search/app/bin/console:43

Hi,

could you provide some more information about the issue? This is related to the Symfony Serializer.

You are used Doctrine as a Messenger transport, am I right?
Then a class of yours is called: src/Util/IndexJsonSerializer.php, what is it?

Oh, yes,
My service is a proxy between external data-house and elasticsearch server. So, I don't use doctrine for ingesting the data.
The flow is when the data request comes to the indexation it is transformed to the elastic search maps, then goes to the messenger for further indexation and logging - here is exactly the place where I call schedule() functions.

My IndexJsonSerializer created just for having camelCase name converter added to the default symfony serializer.

Without seeing some code I'm not able to help sorry.

One possibility could be that your custom IndexJsonSerializer mess with the Serializer used inside the Messenger component of Symfony. Each "Message" is serialized in the transport (Doctrine here but it does not matter). When a Message is received, the denormalizer is called, and from what I can see, that's where you have a issue: Symfony is not able to rebuild the Message DTO properly.

There is also probably a bug in the Error Handler too that prevent you from seeing the real issue.

https://github.com/symfony/symfony/blob/20e5441eb893f9da932b529dcd9f8e254bbf0cc5/src/Symfony/Component/PropertyAccess/PropertyAccessor.php#L541 throw the exception.

May I suggest you remove your custom converter to test the behavior again?

Well, it appears to hard to describe.
Currently, I see " #message: "Return value of JoliCode\Elastically\Client::getSerializer() must implement interface Symfony\Component\Serializer\SerializerInterface, string returned" if I set elastically_serializer: App\Util\JsonIndexSerializer

...
use Symfony\Component\Serializer\SerializerInterface;

class IndexJsonSerializer implements SerializerInterface
{
    private Serializer $serializer;

    public function __construct()
    {
        $normalizers = [
            new PropertyNormalizer(),
            new ArrayDenormalizer(),
            new DateTimeNormalizer(),
            new ObjectNormalizer(
                new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())),
                new CamelCaseToSnakeCaseNameConverter(),
                null,
                new PhpDocExtractor()
            ),
        ];

        $encoders = [
            new JsonEncoder()
        ];

        $this->serializer = new Serializer($normalizers, $encoders);
    }

    public function serialize($data, string $format, array $context = []): string
    {
        return $this->serializer->serialize($data, 'json', $context);
    }

    public function deserialize($data, string $type, string $format, array $context = [])
    {
        return $this->serializer->deserialize($data, $type, 'json', $context);
    }
}

But this has nothing to do with your original error?

To fix this may I suggest you had an alias on your custom service and reference it with the @ marker?

App\Util\JsonIndexSerializer:
    alias: my_serializer

elastically:
    elastically_serializer: @my_serializer

I read your latest article and decide to use the library by the way. Could you correct me if I have created the config wrong in config/packages/elastically.yaml and wrote the next

services:

  JoliCode\Elastically\Transport\HttpClientTransport: ~
  JoliCode\Elastically\Messenger\IndexationRequestHandler: ~
  JoliCode\Elastically\Client:
    arguments:
      $config:
        host: '%env(ELASTICSEARCH_HOST)%'
        port: '%env(ELASTICSEARCH_PORT)%'
        transport: '@JoliCode\Elastically\Transport\HttpClientTransport'
        elastically_mappings_directory: '%kernel.project_dir%/config/elastically_maps'
        elastically_index_class_mapping:
          medicine: App\Model\MedicineModel
        elastically_serializer: '@app_index_serializer'
        elastically_bulk_size: 10
      $logger: '@logger'

  JoliCode\Elastically\Messenger\DocumentExchangerInterface:
    alias: App\Elasticsearch\MedicineDocumentExchanger

Can I remove that and just keep the elastically.yaml with related config not. directly bound to the $config variable?

Hello, Alexandre,
I think I am closing this ticket because I found the workaround - re-create my models so it doesn't require a new serializer. Need to move forward. Appreciate your help and the development!!