Skip to content

FiberError in PHP-FPM #85

Description

@iGrog

I ran into an issue and wanted to check if I’m using the client incorrectly.

My setup
I’m using Symfony + PHP-FPM.
thesis/amqp is used to publish messages to RabbitMQ from HTTP requests.
So this is not a long-running consumer, but a short request lifecycle:

request comes in → publish message → return response → process ends

(technically FPM workers are reused, but each request is short-lived).
Code example

final class AmqpPublish implements TransportPublish
{
    private ?Channel $channel = null;

    public function __construct(
        private readonly Client $client,
    ) {}

    public function publish(array $envelopes): void
    {
        if ($this->channel === null) {
            $this->channel = $this->client->channel();
        }

        foreach ($envelopes as $envelope) {
            $this->channel->publish(
                message: $this->encoder->encode($envelope),
                exchange: $exchange,
            );
        }

        // Question: is this needed?
        $this->channel = null;
        $this->client->disconnect();
    }
}

Problem
If I do NOT call disconnect() after publishing, then at the end of the PHP-FPM request, Client::__destruct() throws:

FiberError: Cannot resume a fiber that is not suspended.

It seems that the reader fiber created during connect() remains in an invalid state, and revolt cannot properly shut it down during request shutdown.
If I do call disconnect(), it still throws a FiberError, but now inside disconnect() itself.
Currently, I’m working around it like this:

try {
    $this->client->disconnect();
} catch (\FiberError) {
    // suppress
}

This works — messages are published, consumers receive them, everything seems fine. But it feels like a workaround rather than a proper solution.

Questions:

  • Is it correct to use thesis/amqp in PHP-FPM (short request lifecycle), or is it designed primarily for long-running processes?
  • Should I explicitly call disconnect() after publish in PHP-FPM, or should __destruct() handle cleanup?
  • Is FiberError in the destructor expected behavior or a bug?
    With 1.0.2, I had a similar workaround with disconnect(), and it worked without FiberError.
    With 1.1.x-dev, FiberError is thrown both in disconnect() and in __destruct().

Environment:

  • PHP 8.5.2
  • revolt/event-loop ^1.0
  • thesis/amqp 1.1.x-dev
  • Symfony 8.x, PHP-FPM

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions