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

[Messenger] Add serializer usage to InMemoryTransport #38893

Closed
tyx opened this issue Oct 30, 2020 · 8 comments · Fixed by #39075
Closed

[Messenger] Add serializer usage to InMemoryTransport #38893

tyx opened this issue Oct 30, 2020 · 8 comments · Fixed by #39075

Comments

@tyx
Copy link
Contributor

tyx commented Oct 30, 2020

Description

Use $serializer inside the InMemoryTransport.

Currently the in memory transport does not use the serializer compared to the others.

This removes the possibility in tests with messenger to test to the end the chain when a custom serializer is provided (in this case https://github.com/Happyr/message-serializer).

I've created my own transport and I wonder if it could be implemented directly in messenger.

WDYT ?

Example

<?php declare(strict_types=1);

namespace Gogaille\Shared\Messaging;

use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Transport\Serialization\PhpSerializer;
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
use Symfony\Component\Messenger\Transport\TransportInterface;
use Symfony\Contracts\Service\ResetInterface;

/**
 * Copy/Paste from InMemoryTransport of symfony  with serialization.
 */
class InMemorySerializableTransport implements TransportInterface, ResetInterface
{
    /**
     * @var mixed[]
     */
    private $sent = [];

    /**
     * @var mixed[]
     */
    private $acknowledged = [];

    /**
     * @var mixed[]
     */
    private $rejected = [];

    /**
     * @var mixed[]
     */
    private $queue = [];

    private $serializer;

    public function __construct(SerializerInterface $serializer = null)
    {
        $this->serializer = $serializer ?? new PhpSerializer();
    }

    /**
     * {@inheritdoc}
     */
    public function get(): iterable
    {
        return array_values($this->decode($this->queue));
    }

    /**
     * {@inheritdoc}
     */
    public function ack(Envelope $envelope): void
    {
        $this->acknowledged[] = $this->serializer->encode($envelope);
        $id = spl_object_hash($envelope->getMessage());
        unset($this->queue[$id]);
    }

    /**
     * {@inheritdoc}
     */
    public function reject(Envelope $envelope): void
    {
        $this->rejected[] = $this->serializer->encode($envelope);
        $id = spl_object_hash($envelope->getMessage());
        unset($this->queue[$id]);
    }

    /**
     * {@inheritdoc}
     */
    public function send(Envelope $envelope): Envelope
    {
        $encodedEnvelope = $this->serializer->encode($envelope);
        $this->sent[] = $encodedEnvelope;
        $id = spl_object_hash($envelope->getMessage());
        $this->queue[$id] = $encodedEnvelope;

        return $envelope;
    }

    public function reset()
    {
        $this->sent = $this->queue = $this->rejected = $this->acknowledged = [];
    }

    /**
     * @return Envelope[]
     */
    public function getAcknowledged(): array
    {
        return $this->decode($this->acknowledged);
    }

    /**
     * @return Envelope[]
     */
    public function getRejected(): array
    {
        return $this->decode($this->rejected);
    }

    /**
     * @return Envelope[]
     */
    public function getSent(): array
    {
        return $this->decode($this->sent);
    }

    /**
     * @param array<mixed> $messagesEncoded
     *
     * @return Envelope[]
     */
    private function decode(array $messagesEncoded): array
    {
        return array_map(
            fn ($message) => $this->serializer->decode($message),
            $messagesEncoded
        );
    }
}
@tyx tyx changed the title [Messenger] Add serializer to InMemoryTransport [Messenger] Add serializer usage to InMemoryTransport Oct 30, 2020
@chalasr
Copy link
Member

chalasr commented Oct 30, 2020

Looks sensible to me.

@Nyholm
Copy link
Member

Nyholm commented Oct 30, 2020

I agree with this.
Sure it will "just take time", but it makes my development environment a bit more similar to how it works in production.

👍

@Nyholm
Copy link
Member

Nyholm commented Oct 30, 2020

Could we make this configurable with in-memory://?serialse=true?

Just make sure we use the configured (or default) serializer.

@Guikingone
Copy link
Contributor

Guikingone commented Oct 30, 2020

What about adding a FilesystemTransport ?

This way, the InMemoryTransport can stay as it and we can use a new transport dedicated to test env?

@tyx
Copy link
Contributor Author

tyx commented Oct 30, 2020

Could we make this configurable with in-memory://?serialse=true?

Just make sure we use the configured (or default) serializer.

Yes indeed ! Love this idea

@tyx
Copy link
Contributor Author

tyx commented Oct 30, 2020

What about adding a FilesystemTransport ?

This way, the InMemoryTransport can stay as it and we can use a new transport dedicated to test env?

InMemory is not already dedicated to test env ?

@Guikingone
Copy link
Contributor

InMemory is not already dedicated to test env ?

You're right, my bad, I was thinking about a new transport as IMHO it's easier to maintain and improve rather than adding a new option and impacting the existing InMemoryTransport.

@derrabus
Copy link
Member

What about adding a FilesystemTransport ?

IIRC think that idea was discarded in the past because you could basically use a Doctrine transport on an SQLite file to achieve a "filesystem transport".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants