Comments (11)
Fixed the URL of the openqa issue - https://github.com/inway/mojo-rabbitmq-client/blob/master/lib/Mojo/RabbitMQ/Client/Channel.pm#L641 is the point of the DESTROY
from mojo-rabbitmq-client.
I'm wondering about the right choice of action when a fork is detected.
Should it behave in a similar way to DBIx::Class and create new connection everytime it forks? What about current subscriptions and many other things to take into account...
from mojo-rabbitmq-client.
I think it might be smart to just do the same thing Mojo::UserAgent
and Mojo::Pg
do. Reset the connection pool after fork, and make sure the parent connection does not get corrupted. If nobody else is working on this yet i'll take a look tomorrow.
from mojo-rabbitmq-client.
I was just thinking about hypothetical use case when you open client, consume a message, fork and execute some long running task, and then publish a reply on a different channel. This might as well be just some edge case, that will never be thought of.
Resetting connection pool will probably be less error-prone.
from mojo-rabbitmq-client.
for the record: I worked around the issue for me by just not having open connections around and using the Publisher API. This is a little slower and it's still possible that we run into this problem, but it reduces the problem for me.
from mojo-rabbitmq-client.
Trying to replicate the problem turned out to be way more complicated than i expected. Because a connection created with the Mojo::RabbitMQ::Client
promise API results in 24+ circular references that prevent the destruction of the channel. Which also has me a little worried that @coolo's workaround might be leaking memory.
Cycle (1):
$Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'client'} => \%Mojo::RabbitMQ::Client::C
$Mojo::RabbitMQ::Client::C->{'channels'} => \%D
$D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
Unhandled type: GLOB at /usr/lib/perl5/vendor_perl/5.26.2/Devel/Cycle.pm line 107.
Cycle (2):
$Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'client'} => \%Mojo::RabbitMQ::Client::C
$Mojo::RabbitMQ::Client::C->{'ioloop'} => \%Mojo::IOLoop::E
$Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
$Mojo::Reactor::Poll::F->{'timers'} => \%G
$G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
$H->{'cb'} => \&I
$I variable $cb => \$J
$$J => \&K
$K variable $consumer => \$L
$$L => \%Mojo::RabbitMQ::Client::Method::A
Cycle (3):
$Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
$M->{'error'} => \@N
$N->[0] => \&O
$O variable $promise => \$P
$$P => \%Mojo::Promise::Q
$Mojo::Promise::Q->{'ioloop'} => \%Mojo::IOLoop::E
$Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
$Mojo::Reactor::Poll::F->{'timers'} => \%G
$G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
$H->{'cb'} => \&I
$I variable $cb => \$J
$$J => \&K
$K variable $consumer => \$L
$$L => \%Mojo::RabbitMQ::Client::Method::A
Cycle (4):
$Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
$M->{'error'} => \@N
$N->[0] => \&O
$O variable $promise => \$P
$$P => \%Mojo::Promise::Q
$Mojo::Promise::Q->{'result'} => \@R
$R->[0] => \%Mojo::RabbitMQ::Client::Channel::B
Cycle (5):
$Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
$M->{'open'} => \@S
$S->[0] => \&T
$T variable $promise => \$P
$$P => \%Mojo::Promise::Q
$Mojo::Promise::Q->{'ioloop'} => \%Mojo::IOLoop::E
$Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
$Mojo::Reactor::Poll::F->{'timers'} => \%G
$G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
$H->{'cb'} => \&I
$I variable $cb => \$J
$$J => \&K
$K variable $consumer => \$L
$$L => \%Mojo::RabbitMQ::Client::Method::A
Cycle (6):
$Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
$M->{'open'} => \@S
$S->[0] => \&T
$T variable $promise => \$P
$$P => \%Mojo::Promise::Q
$Mojo::Promise::Q->{'result'} => \@R
$R->[0] => \%Mojo::RabbitMQ::Client::Channel::B
Cycle (7):
$Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'queue'} => \%Mojo::RabbitMQ::Client::LocalQueue::U
$Mojo::RabbitMQ::Client::LocalQueue::U->{'drain_code_queue'} => \@V
$V->[0] => \&W
$W variable $cb => \$X
$$X => \&Y
$Y variable $self => \$Z
$$Z => \%Mojo::RabbitMQ::Client::Method::A
Cycle (8):
$Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'queue'} => \%Mojo::RabbitMQ::Client::LocalQueue::U
$Mojo::RabbitMQ::Client::LocalQueue::U->{'drain_code_queue'} => \@V
$V->[0] => \&W
$W variable $failure_cb => \$AA
$$AA => \&AB
$AB variable $self => \$Z
$$Z => \%Mojo::RabbitMQ::Client::Method::A
Cycle (9):
$Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
$Mojo::RabbitMQ::Client::C->{'channels'} => \%D
$D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'client'} => \%Mojo::RabbitMQ::Client::C
Cycle (10):
$Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
$Mojo::RabbitMQ::Client::C->{'channels'} => \%D
$D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
$M->{'error'} => \@N
$N->[0] => \&O
$O variable $promise => \$P
$$P => \%Mojo::Promise::Q
$Mojo::Promise::Q->{'ioloop'} => \%Mojo::IOLoop::E
$Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
$Mojo::Reactor::Poll::F->{'timers'} => \%G
$G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
$H->{'cb'} => \&I
$I variable $cb => \$J
$$J => \&K
$K variable $consumer => \$L
$$L => \%Mojo::RabbitMQ::Client::Method::A
Cycle (11):
$Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
$Mojo::RabbitMQ::Client::C->{'channels'} => \%D
$D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
$M->{'error'} => \@N
$N->[0] => \&O
$O variable $promise => \$P
$$P => \%Mojo::Promise::Q
$Mojo::Promise::Q->{'result'} => \@R
$R->[0] => \%Mojo::RabbitMQ::Client::Channel::B
Cycle (12):
$Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
$Mojo::RabbitMQ::Client::C->{'channels'} => \%D
$D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
$M->{'open'} => \@S
$S->[0] => \&T
$T variable $promise => \$P
$$P => \%Mojo::Promise::Q
$Mojo::Promise::Q->{'ioloop'} => \%Mojo::IOLoop::E
$Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
$Mojo::Reactor::Poll::F->{'timers'} => \%G
$G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
$H->{'cb'} => \&I
$I variable $cb => \$J
$$J => \&K
$K variable $consumer => \$L
$$L => \%Mojo::RabbitMQ::Client::Method::A
Cycle (13):
$Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
$Mojo::RabbitMQ::Client::C->{'channels'} => \%D
$D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
$M->{'open'} => \@S
$S->[0] => \&T
$T variable $promise => \$P
$$P => \%Mojo::Promise::Q
$Mojo::Promise::Q->{'result'} => \@R
$R->[0] => \%Mojo::RabbitMQ::Client::Channel::B
Cycle (14):
$Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
$Mojo::RabbitMQ::Client::C->{'channels'} => \%D
$D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'queue'} => \%Mojo::RabbitMQ::Client::LocalQueue::U
$Mojo::RabbitMQ::Client::LocalQueue::U->{'drain_code_queue'} => \@V
$V->[0] => \&W
$W variable $cb => \$X
$$X => \&Y
$Y variable $self => \$Z
$$Z => \%Mojo::RabbitMQ::Client::Method::A
Cycle (15):
$Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
$Mojo::RabbitMQ::Client::C->{'channels'} => \%D
$D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'queue'} => \%Mojo::RabbitMQ::Client::LocalQueue::U
$Mojo::RabbitMQ::Client::LocalQueue::U->{'drain_code_queue'} => \@V
$V->[0] => \&W
$W variable $failure_cb => \$AA
$$AA => \&AB
$AB variable $self => \$Z
$$Z => \%Mojo::RabbitMQ::Client::Method::A
Cycle (16):
$Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
$Mojo::RabbitMQ::Client::C->{'ioloop'} => \%Mojo::IOLoop::E
$Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
$Mojo::Reactor::Poll::F->{'timers'} => \%G
$G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
$H->{'cb'} => \&I
$I variable $cb => \$J
$$J => \&K
$K variable $consumer => \$L
$$L => \%Mojo::RabbitMQ::Client::Method::A
Cycle (17):
$Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
$AC->{'success'} => \@AD
$AD->[0] => \&AE
$AE variable $self => \$AF
$$AF => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'client'} => \%Mojo::RabbitMQ::Client::C
$Mojo::RabbitMQ::Client::C->{'channels'} => \%D
$D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
Cycle (18):
$Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
$AC->{'success'} => \@AD
$AD->[0] => \&AE
$AE variable $self => \$AF
$$AF => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'client'} => \%Mojo::RabbitMQ::Client::C
$Mojo::RabbitMQ::Client::C->{'ioloop'} => \%Mojo::IOLoop::E
$Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
$Mojo::Reactor::Poll::F->{'timers'} => \%G
$G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
$H->{'cb'} => \&I
$I variable $cb => \$J
$$J => \&K
$K variable $consumer => \$L
$$L => \%Mojo::RabbitMQ::Client::Method::A
Cycle (19):
$Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
$AC->{'success'} => \@AD
$AD->[0] => \&AE
$AE variable $self => \$AF
$$AF => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
$M->{'error'} => \@N
$N->[0] => \&O
$O variable $promise => \$P
$$P => \%Mojo::Promise::Q
$Mojo::Promise::Q->{'ioloop'} => \%Mojo::IOLoop::E
$Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
$Mojo::Reactor::Poll::F->{'timers'} => \%G
$G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
$H->{'cb'} => \&I
$I variable $cb => \$J
$$J => \&K
$K variable $consumer => \$L
$$L => \%Mojo::RabbitMQ::Client::Method::A
Cycle (20):
$Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
$AC->{'success'} => \@AD
$AD->[0] => \&AE
$AE variable $self => \$AF
$$AF => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
$M->{'error'} => \@N
$N->[0] => \&O
$O variable $promise => \$P
$$P => \%Mojo::Promise::Q
$Mojo::Promise::Q->{'result'} => \@R
$R->[0] => \%Mojo::RabbitMQ::Client::Channel::B
Cycle (21):
$Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
$AC->{'success'} => \@AD
$AD->[0] => \&AE
$AE variable $self => \$AF
$$AF => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
$M->{'open'} => \@S
$S->[0] => \&T
$T variable $promise => \$P
$$P => \%Mojo::Promise::Q
$Mojo::Promise::Q->{'ioloop'} => \%Mojo::IOLoop::E
$Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
$Mojo::Reactor::Poll::F->{'timers'} => \%G
$G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
$H->{'cb'} => \&I
$I variable $cb => \$J
$$J => \&K
$K variable $consumer => \$L
$$L => \%Mojo::RabbitMQ::Client::Method::A
Cycle (22):
$Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
$AC->{'success'} => \@AD
$AD->[0] => \&AE
$AE variable $self => \$AF
$$AF => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
$M->{'open'} => \@S
$S->[0] => \&T
$T variable $promise => \$P
$$P => \%Mojo::Promise::Q
$Mojo::Promise::Q->{'result'} => \@R
$R->[0] => \%Mojo::RabbitMQ::Client::Channel::B
Cycle (23):
$Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
$AC->{'success'} => \@AD
$AD->[0] => \&AE
$AE variable $self => \$AF
$$AF => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'queue'} => \%Mojo::RabbitMQ::Client::LocalQueue::U
$Mojo::RabbitMQ::Client::LocalQueue::U->{'drain_code_queue'} => \@V
$V->[0] => \&W
$W variable $cb => \$X
$$X => \&Y
$Y variable $self => \$Z
$$Z => \%Mojo::RabbitMQ::Client::Method::A
Cycle (24):
$Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
$AC->{'success'} => \@AD
$AD->[0] => \&AE
$AE variable $self => \$AF
$$AF => \%Mojo::RabbitMQ::Client::Channel::B
$Mojo::RabbitMQ::Client::Channel::B->{'queue'} => \%Mojo::RabbitMQ::Client::LocalQueue::U
$Mojo::RabbitMQ::Client::LocalQueue::U->{'drain_code_queue'} => \@V
$V->[0] => \&W
$W variable $failure_cb => \$AA
$$AA => \&AB
$AB variable $self => \$Z
$$Z => \%Mojo::RabbitMQ::Client::Method::A
from mojo-rabbitmq-client.
Pretty much everything leaks a lot as it turns out, including the publisher API (8 circular references). I'll be sending a patch for that.
from mojo-rabbitmq-client.
So, I'm now trying to use the openQA AMQP bits to publish to fedora-messaging (what fun we're all having!) One thing I noticed is these errors popping up in the logs:
Aug 01 23:40:59 openqa-stg01.qa.fedoraproject.org openqa[12692]: Mojo::Reactor::Poll: I/O watcher failed: Can't call method "_handle" on an undefined value at /usr/share/perl5/vendor_perl/Mojo/RabbitMQ/Client.pm line 372.
Aug 01 23:40:59 openqa-stg01.qa.fedoraproject.org openqa[12692]: Mojo::Reactor::Poll: I/O watcher failed: Can't call method "_handle" on an undefined value at /usr/share/perl5/vendor_perl/Mojo/RabbitMQ/Client.pm line 372.
Aug 01 23:41:04 openqa-stg01.qa.fedoraproject.org openqa[12692]: Mojo::Reactor::Poll: I/O watcher failed: Can't call method "_read" on an undefined value at /usr/share/perl5/vendor_perl/Mojo/RabbitMQ/Client.pm line 374.
Aug 01 23:41:04 openqa-stg01.qa.fedoraproject.org openqa[12692]: Mojo::Reactor::Poll: I/O watcher failed: Can't call method "_read" on an undefined value at /usr/share/perl5/vendor_perl/Mojo/RabbitMQ/Client.pm line 374.
those are happening here:
# Connection established
$stream->on(timeout => sub { $self->_error($id, 'Inactivity timeout') });
$stream->on(close => sub { $self->_handle($id, 1) });
$stream->on(error => sub { $self && $self->_error($id, pop) });
$stream->on(read => sub { $self->_read($id, pop) });
$cb->();
it seems $id
is undefined sometimes. I honestly am not sure exactly how or by what it's supposed to be defined at the point those subroutines are called, all this async stuff screws with my head. But is it related to this, perhaps? If not, I can file a separate issue. @kraih @coolo have you seen these errors also?
from mojo-rabbitmq-client.
yes, we see these errors all the time reproducibly e.g. on openqa.opensuse.org. The originally referenced progress ticket also links to another ticket that is describing this issue as well: https://progress.opensuse.org/issues/52961
so for sure there seems to be no relevant functional impact but no clean shutdown of the streams triggering the above error.
from mojo-rabbitmq-client.
@AdamWill at least the warnings about undef objects are handled in #36 . Not sure if this is the last missing piece to close this issue though.
from mojo-rabbitmq-client.
Thanks 👍
from mojo-rabbitmq-client.
Related Issues (20)
- Early success event from ->publish HOT 2
- Implement blocking publisher API HOT 3
- Update documentation
- Proper tests for all Promise methods
- Circular includes
- Making Mojo::RabbitMQ::Client::Consumer use promises HOT 1
- Mojo::RabbitMQ::Client gets destroyed too soon using morbo HOT 1
- Unable to use consumer API
- Publisher documentation's examples are hard to parse HOT 1
- repo and tarballs include non-free file without notification HOT 1
- 'weaken $self' leads to undefined errors
- Body larger than frame_max not split into multiple frames
- RMQ message not sent intermittently
- Client disconnect doc example uses 'close' HOT 1
- publish with mandatory but without routing_key leads to uninitialized warning
- is_open incorrect after disconnect event
- hard to debug connection failure
- How to reject a message and I'd like to contribute
- Disabling TLS certificate validation doesn't work
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mojo-rabbitmq-client.