Skip to content

Conversation

@WyriHaximus
Copy link
Collaborator

@WyriHaximus WyriHaximus commented Aug 26, 2025

  • Add fiber examples for all examples in the readme
  • Convert the benchmark to be encapsulated in fibers
  • Convert the tutorials to be encapsulated in fibers

@pulmer-cp @mdissington @andrew-demb @menturion @kostirez1 Since you either created or responded/emoted to some message in #192 or #191 I would love your feedback on this PR, addressing that in the documentation and examples. The changes in the readme start here: https://github.com/jakubkulhan/bunny/tree/0.6.x-make-it-abundantly-clear-Bunny-must-run-in-a-fiber?tab=readme-ov-file#always-run-moving-parts-in-a-fiber

@WyriHaximus WyriHaximus added this to the v0.6.0 milestone Aug 26, 2025
@kostirez1
Copy link

Thank you so much for extending the documentation!

What I was looking for was a way to upgrade contributte/rabbitmq, that relies on the $client->run() synchronous helper method present in 0.5.x. If I understand it correctly, helper methods are the goal of #178, making the upgrade path much more straightforward. ❤️

@mdissington
Copy link

I think I saw "Cannot switch fibers in current execution context" when I was trying to shut my service down in a signal handler, I take it in that situation it is running outside of a fiber context?

I think I fixed it by calling my shutdown code in a Loop::futureTick(). I wasn't sure if I was doing things the "correct" way but it looks like I may have guessed correctly? :-)

@menturion
Copy link

I think I saw "Cannot switch fibers in current execution context" when I was trying to shut my service down in a signal handler, I take it in that situation it is running outside of a fiber context?

I think I fixed it by calling my shutdown code in a Loop::futureTick(). I wasn't sure if I was doing things the "correct" way but it looks like I may have guessed correctly? :-)

That's also exactly my case, terminating a worker via signal handler:

        $signals = [SIGINT, SIGTERM, SIGHUP];

        foreach ($signals as $signal) {
            Loop::addSignal($signal, static function () use ($consumerTag): void {
               self::_disconnect($consumerTag);
            });
        }

Within the _disconnect() method, I call the cancel(...) method for the channel object and disconnect() for the client object.

Copy link

@andrew-demb andrew-demb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, thank you. I left some suggestions to improve it a bit from my PoV

README.md Outdated
$bunny->connect(); // No perse needed, as the Client::channel() method also does this, but added for completeness sake
$channel = $bunny->channel();
$channel->queueDeclare('queue_name'); // Queue name
$channel->close(); // No perse needed, as the Client::disconnect() method also does this, but added for completeness sake

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does it mean "No perse needed"? I'm not sure about the translation.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spotted this, I think he may have meant "Not needed per se, as the Client..."?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest rephrasing it then to make it clear 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, the client will open a connection when you try to open a channel if it's not connected or in the process of connecting:

bunny/src/Client.php

Lines 155 to 170 in 5a37f76

/**
* Creates and opens new channel.
*
* Channel gets first available channel id.
*/
public function channel(): ChannelInterface
{
if (!$this->isConnected()) {
$this->connect();
}
if ($this->state === ClientState::Connecting) {
$this->awaitConnection();
}
$channelId = $this->findChannelId();

Technically, that means there is no need to call Client::connect() directly, making Bunny on the connecting side lazy.

Similarly, when calling Client::disconnect(), it will close all open channels

bunny/src/Client.php

Lines 290 to 297 in 5a37f76

$promises = [];
foreach ($this->channels->all() as $channelId => $channel) {
$promises[] = async(static function () use ($channel, $replyCode, $replyText): void {
$channel->close($replyCode, $replyText);
})();
}
await(all($promises));
. Thus, you don't have to call Channel::close() when disconnecting.

Updated the message a bit, but I can also remove them.

);

$bunny = new Client($configuration);
Loop::futureTick(async(static function (): void {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it necessary to use Loop::futureTick, but not async? I'm not sure whether it is a necessary detail to be known by the developer for classic use cases (php-fpm with no full async application)

Copy link
Collaborator Author

@WyriHaximus WyriHaximus Aug 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it necessary to use Loop::futureTick, but not async?

Loop::futureTick isn't strictly necessary, async is tho. You could do async(static fn etc etc)() to start the fiber right away, but using a Loop::futureTick schedules it right after the event loop has finished all it's incoming working from the kernel.

I'm not sure whether it is a necessary detail to be known by the developer for classic use cases (php-fpm with no full async application)

It shouldn't matter to them. Will have a look at adding a section for that tomorrow.

@WyriHaximus WyriHaximus force-pushed the 0.6.x-make-it-abundantly-clear-Bunny-must-run-in-a-fiber branch from b6d19cf to 0b7cdbe Compare August 28, 2025 22:00
@WyriHaximus
Copy link
Collaborator Author

Thank you so much for extending the documentation!

What I was looking for was a way to upgrade contributte/rabbitmq, that relies on the $client->run() synchronous helper method present in 0.5.x. If I understand it correctly, helper methods are the goal of #178, making the upgrade path much more straightforward. ❤️

Correct, and @andrew-demb also made some good points on this topic.

Haven't been able to respond to everything, but pushed some changes based on suggestions.

@WyriHaximus WyriHaximus force-pushed the 0.6.x-make-it-abundantly-clear-Bunny-must-run-in-a-fiber branch from 0b7cdbe to 6351b75 Compare September 1, 2025 14:52
@WyriHaximus
Copy link
Collaborator Author

I think I saw "Cannot switch fibers in current execution context" when I was trying to shut my service down in a signal handler, I take it in that situation it is running outside of a fiber context?

I think I fixed it by calling my shutdown code in a Loop::futureTick(). I wasn't sure if I was doing things the "correct" way but it looks like I may have guessed correctly? :-)

I think I saw "Cannot switch fibers in current execution context" when I was trying to shut my service down in a signal handler, I take it in that situation it is running outside of a fiber context?
I think I fixed it by calling my shutdown code in a Loop::futureTick(). I wasn't sure if I was doing things the "correct" way but it looks like I may have guessed correctly? :-)

That's also exactly my case, terminating a worker via signal handler:

        $signals = [SIGINT, SIGTERM, SIGHUP];

        foreach ($signals as $signal) {
            Loop::addSignal($signal, static function () use ($consumerTag): void {
               self::_disconnect($consumerTag);
            });
        }

Within the _disconnect() method, I call the cancel(...) method for the channel object and disconnect() for the client object.

Just pushed updated quickstart examples that cover this, also added the logic to both consumer examples in the readme.

@WyriHaximus WyriHaximus force-pushed the 0.6.x-make-it-abundantly-clear-Bunny-must-run-in-a-fiber branch from 6351b75 to c5d046e Compare September 18, 2025 22:40
WyriHaximus added a commit that referenced this pull request Oct 25, 2025
WyriHaximus added a commit that referenced this pull request Oct 25, 2025
@WyriHaximus WyriHaximus force-pushed the 0.6.x-make-it-abundantly-clear-Bunny-must-run-in-a-fiber branch from c5d046e to eff8c15 Compare October 25, 2025 14:24
WyriHaximus added a commit that referenced this pull request Oct 25, 2025
WyriHaximus added a commit that referenced this pull request Oct 25, 2025
WyriHaximus added a commit that referenced this pull request Oct 25, 2025
WyriHaximus added a commit that referenced this pull request Oct 25, 2025
WyriHaximus added a commit that referenced this pull request Oct 26, 2025
@WyriHaximus WyriHaximus force-pushed the 0.6.x-make-it-abundantly-clear-Bunny-must-run-in-a-fiber branch from eff8c15 to 69c683d Compare October 26, 2025 11:02
@WyriHaximus WyriHaximus merged commit b0e9af0 into 0.6.x Nov 9, 2025
183 checks passed
@WyriHaximus WyriHaximus deleted the 0.6.x-make-it-abundantly-clear-Bunny-must-run-in-a-fiber branch November 9, 2025 12:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants