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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions