|
View:
New views
18 Messages
—
Rating Filter:
Alert me
|
|
|
Channel CostIs it costly in Rabbit to open and close channels frequently? The
reason I ask is that you can't pickup errors from a basic_publish in py-ampqlib until you close the channel. -J _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostJason,
Jason J. W. Williams wrote: > Is it costly in Rabbit to open and close channels frequently? Yes. > The reason I ask is that you can't pickup errors from a basic_publish > in py-ampqlib until you close the channel. What do you mean by "errors"? There are two types of errors that can arise when the server processes a basic.publish command. AMQP errors, such as malformed requests, missing exchange, etc, close the channel or connection automatically. Routing failures of messages with the 'mandatory' or 'immediate' flag are signalled to the client with an asynchronous basic.return command. Are you saying that in py-amqplib there is no way to get hold of the latter until channel closure? If so that would seem to be an omission in the library and I suggest you take that up with the authors. Matthias. _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostHi Jason,
Jason J. W. Williams wrote: > Is it costly in Rabbit to open and close channels frequently? The > reason I ask is that you can't pickup errors from a basic_publish in > py-ampqlib until you close the channel. > Could this suggestion by Matthias help you (second to last paragraph): http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2008-November/002539.html - Dmitriy _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostIs there a more appropriate venue for AMQP users to gather and puzzle
out what's what? I feel a lack of community around my attempts to puzzle out what design patterns are good, and what AMQP expects of me. On Jan 26, 2009, at 9:25 PM, Jason J. W. Williams wrote: > ... you can't pickup errors from a basic_publish in > py-ampqlib until you close the channel ... One thing I'm having trouble with is getting a clear model of how responsibility for a message moves around. Basic publish tosses responsibility, and it's - ah - later that you _might_ infer or be told that it didn't work out. That is the point of "2.2.3 No Confirmations" in "Advanced Message Queuing Protocol Specification [0.8 June 2006]". On Jan 27, 2009, at 4:13 AM, Matthias Radestock wrote: > What do you mean by "errors"? indeed ... great list! > There are two types of errors that can > arise when the server processes a basic.publish command. AMQP errors, > such as malformed requests, missing exchange, etc, close the channel > or > connection automatically. Assuring that all these are raised and caught provides no end of amusement. There doesn't appear to be a way for the server to signal these errors short of tearing down the connection. So catching this is a matter for your heartbeats or your doing it at the transport layer. Correct? > Routing failures of messages with the > 'mandatory' or 'immediate' flag are signalled to the client with an > asynchronous basic.return command. > Are you saying that in py-amqplib there is no way to get hold of the > latter until channel closure? If I'm reading the code correctly the client (next time it reads from the channel) will dispatch to the basic_return method of the Channel object. The Channel class does not have that method defined. I could be wrong. > If so that would seem to be an omission in > the library and I suggest you take that up with the authors. True that. Crosstalk is good. Py-amqplib is an important complement to rabbitmq. There isn't a py-ampqlib mailing list, correct? On Jan 27, 2009, at 10:24 AM, Dmitriy Samovskiy wrote: > Could this suggestion by Matthias help you (second to last paragraph): > http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2008-November/002539.html interesting: "issue *any* synchronous command. The response constitutes a guarantee that all messages published prior to the request will have been processed by the channel process on the server." That seems useful. If you had the heart beat enabled would that tell you something similar? Again not interoperable. Do you have a synch. cmd you'd recommend. _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostBen Hyde wrote: > On Jan 27, 2009, at 10:24 AM, Dmitriy Samovskiy wrote: >> Could this suggestion by Matthias help you (second to last paragraph): >> http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2008-November/002539.html > > interesting: "issue *any* synchronous command. The response > constitutes a guarantee that all messages published prior to the > request will have been processed by the channel process on the server." > > That seems useful. If you had the heart beat enabled would that tell > you something similar? Again not interoperable. > > Do you have a synch. cmd you'd recommend. I thought a passive queue or exchange declaration of a known entity might be sufficiently inexpensive: ch.exchange_declare('amq.topic', type='topic', passive=True) DEBUG:amqplib:> (10, 10): Connection.start DEBUG:amqplib:Start from server, version: 8.0, properties: {u'platform': 'Erlang/OTP', u'product': 'RabbitMQ', u'version': '1.5.1', u'copyright': 'Copyright (C) 2007-2009 LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd.', u'information': 'Licensed under the MPL. See http://www.rabbitmq.com/'}, mechanisms: ['PLAIN', 'AMQPLAIN'], locales: ['en_US'] DEBUG:amqplib:< (10, 11): Connection.start_ok DEBUG:amqplib:> (10, 30): Connection.tune DEBUG:amqplib:< (10, 31): Connection.tune_ok DEBUG:amqplib:< (10, 40): Connection.open DEBUG:amqplib:> (10, 41): Connection.open_ok DEBUG:amqplib:Open OK! known_hosts [myvm:5672] DEBUG:amqplib:using channel_id: 1 DEBUG:amqplib:< (20, 10): Channel.open DEBUG:amqplib:> (20, 11): Channel.open_ok DEBUG:amqplib:Channel open DEBUG:amqplib:< (60, 40): Channel.basic_publish DEBUG:amqplib:< (40, 10): Channel.exchange_declare DEBUG:amqplib:> (40, 11): Channel.exchange_declare_ok _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostHi Matthias,
Thank you for the insight. My issue was exactly picking up channel errors like publishing to an exchange that doesn't exist. Unfortunately, py-amqplib doesn't raise the error until you close the channel. I'll look at patching py-amqplib. -J On 1/27/09, Matthias Radestock <matthias@...> wrote: > Jason, > > Jason J. W. Williams wrote: >> Is it costly in Rabbit to open and close channels frequently? > > Yes. > >> The reason I ask is that you can't pickup errors from a basic_publish >> in py-ampqlib until you close the channel. > > What do you mean by "errors"? There are two types of errors that can > arise when the server processes a basic.publish command. AMQP errors, > such as malformed requests, missing exchange, etc, close the channel or > connection automatically. Routing failures of messages with the > 'mandatory' or 'immediate' flag are signalled to the client with an > asynchronous basic.return command. > > Are you saying that in py-amqplib there is no way to get hold of the > latter until channel closure? If so that would seem to be an omission in > the library and I suggest you take that up with the authors. > > > Matthias. > _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostHi Matthias,
Thank you for the insight. My issue was exactly picking up channel errors like publishing to an exchange that doesn't exist. Unfortunately, py-amqplib doesn't raise the error until you close the channel. I'll look at patching py-amqplib. -J On 1/27/09, Matthias Radestock <matthias@...> wrote: > Jason, > > Jason J. W. Williams wrote: >> Is it costly in Rabbit to open and close channels frequently? > > Yes. > >> The reason I ask is that you can't pickup errors from a basic_publish >> in py-ampqlib until you close the channel. > > What do you mean by "errors"? There are two types of errors that can > arise when the server processes a basic.publish command. AMQP errors, > such as malformed requests, missing exchange, etc, close the channel or > connection automatically. Routing failures of messages with the > 'mandatory' or 'immediate' flag are signalled to the client with an > asynchronous basic.return command. > > Are you saying that in py-amqplib there is no way to get hold of the > latter until channel closure? If so that would seem to be an omission in > the library and I suggest you take that up with the authors. > > > Matthias. > _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostIt looks like I can trigger the error by calling a channel.wait() to
pick up any errors that were triggered by the send. Problem is .wait() is a blocking call and if everything went all right it just hangs up the program. I'll take this over to the py-amqplib folks. -J On Tue, Jan 27, 2009 at 10:19 AM, Jason J. W. Williams <jasonjwwilliams@...> wrote: > Hi Matthias, > > Thank you for the insight. My issue was exactly picking up channel > errors like publishing to an exchange that doesn't exist. > Unfortunately, py-amqplib doesn't raise the error until you close the > channel. I'll look at patching py-amqplib. > > -J > > On 1/27/09, Matthias Radestock <matthias@...> wrote: >> Jason, >> >> Jason J. W. Williams wrote: >>> Is it costly in Rabbit to open and close channels frequently? >> >> Yes. >> >>> The reason I ask is that you can't pickup errors from a basic_publish >>> in py-ampqlib until you close the channel. >> >> What do you mean by "errors"? There are two types of errors that can >> arise when the server processes a basic.publish command. AMQP errors, >> such as malformed requests, missing exchange, etc, close the channel or >> connection automatically. Routing failures of messages with the >> 'mandatory' or 'immediate' flag are signalled to the client with an >> asynchronous basic.return command. >> >> Are you saying that in py-amqplib there is no way to get hold of the >> latter until channel closure? If so that would seem to be an omission in >> the library and I suggest you take that up with the authors. >> >> >> Matthias. >> > > _______________________________________________ > rabbitmq-discuss mailing list > rabbitmq-discuss@... > http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss > _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostJason J. W. Williams wrote:
> It looks like I can trigger the error by calling a channel.wait() to > pick up any errors that were triggered by the send. Problem is .wait() > is a blocking call and if everything went all right it just hangs up > the program. I'll take this over to the py-amqplib folks. How are you triggering errors with the send? Is it with immediate or mandatory flags? It'd be good to have an example that could be the basis for a unittest. Barry _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostBen,
Ben Hyde wrote: > There doesn't appear to be a way for the server to signal these errors > short of tearing down the connection. So catching this is a matter > for your heartbeats or your doing it at the transport layer. Correct? The errors are signalled to the client in a {channel,connection}.close command. When the client responds to that with an 'ok' (or after a timeout) the server closes the underlying tcp connection. So there is plenty of opportunity for the client to report/signal the error. Such notifications are still asynchronous though, since you don't get any positive acks that a message has been successfully published. > interesting: "issue *any* synchronous command. The response > constitutes a guarantee that all messages published prior to the > request will have been processed by the channel process on the server." > > That seems useful. If you had the heart beat enabled would that tell > you something similar? Again not interoperable. > > Do you have a synch. cmd you'd recommend. Heartbeats only tell you whether the other side is still alive. They don't tell you what it has seen/processed. As for what sychronous command to use... - 'access.request' is the cheap since it's currently a no-op ... pending its removal when we implement AMQP 0-9-1. - 'basic.cancel' with a non-existing consumer tag is very cheap too. - Another option is 'channel.flow', which for the RabbitMQ server is a no-op (until we implement it), and hence cheap. Note though that getting a confirmation that the RabbitMQ's channel processes have handled a message may not provide you enough of a guarantee. The messages may not have been enqueued yet (though setting the 'mandatory' flag will provide that guarantee), and, in case of persistent messages, may not have been flushed to disk yet (nothing you can do about that short of using tx.*). Matthias. _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostHi Barry,
chan_send.basic_publish(msg,exchange=args.exchange,routing_key=args.routing_key) to an exchange that doesn't exist. I was just wrapping that in a try/except, assuming it would raise AMQPChannelError if there was an issue. Unfortunately, it doesn't look like basic_publish has any logic for checking for an error. At this point I'm looking at wrapping .wait() in a decorator that registers an alarm signal and forces an exception if the alarm timer is too long. Either that or I'll have to move to txAMQP to defer the error check. -J On Tue, Jan 27, 2009 at 12:24 PM, Barry Pederson <bp@...> wrote: > Jason J. W. Williams wrote: >> >> It looks like I can trigger the error by calling a channel.wait() to >> pick up any errors that were triggered by the send. Problem is .wait() >> is a blocking call and if everything went all right it just hangs up >> the program. I'll take this over to the py-amqplib folks. > > How are you triggering errors with the send? Is it with immediate or > mandatory flags? It'd be good to have an example that could be the basis > for a unittest. > > Barry > _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostOn Jan 27, 2009, at 2:34 PM, Jason J. W. Williams wrote: > Hi Barry, > > chan_send > .basic_publish > (msg,exchange=args.exchange,routing_key=args.routing_key) > to an exchange that doesn't exist. Sometime ago, as Dmitriy had pointed out, Matthias suggested that a synchronous call to RabbitMQ is a good way to see if it has consumed the frames we previously dispatched to it. And presumably that also allows amqplib a chance to see any errors that consumption sent back. Dmitriy suggested using declare_exchange as possible choice for a synchronous call to the broker, and Matthias made some other suggestions. So in the following ping_channel does a meaningless exchange_declare. Jason's example of how to get basic_publish to have an error: On Jan 27, 2009, at 2:34 PM, Jason J. W. Williams wrote: > ...chan_send > .basic_publish > (msg,exchange=args.exchange,routing_key=args.routing_key) > to an exchange that doesn't exist. .. So the following code does that, followed by calling ping_channel. The transcript below shows amqplib reporting the error as soon as it reads off that the channel is closing. The source: #!/usr/bin/env python import amqplib.client_0_8 as amqp import logging from os import environ def ping_channel(channel): channel.exchange_declare("RANDOMTEXT",type='topic', passive=True) if __name__ == '__main__': logger = logging.getLogger('amqplib') logger.addHandler(logging.StreamHandler()) logger.setLevel(logging.DEBUG) def trace(m): logger.debug('TRACE: ' + m) vhost=environ.get('AMQP_USERID','/') trace('create connection') connection = conn = amqp.Connection(environ.get('AMQP_SERVER','localhost'), userid=environ.get('AMQP_USERID','guest'), password=environ.get('AMQP_USERID','guest'), virtual_host=vhost) trace('create channel') channel = connection.channel() trace('access_request') channel.access_request(vhost, active=True, write=True) exchange_name = environ.get('AMQP_EXCHANGE','ampq.topic') # exchange = channel.exchange_declare(exchange_name, # environ.get('AMQP_EXCHANGE_KIND','topic')) trace('make message') msg = amqp.Message("Hi there", content_type='text/plain') trace('basic_publish') channel.basic_publish(msg, exchange_name, routing_key=environ.get('AMQP_ROUTING_KEY','')) trace('ping') ping_channel(channel) trace('done') The transcript: bash-3.2$ env - PATH=$PATH AMQP_SERVER=192.168.1.2 AMQP_EXCHANGE=bogus bin/foo.py TRACE: create connection > (10, 10): Connection.start Start from server, version: 8.0, properties: {u'platform': 'Erlang/ OTP', u'product': 'RabbitMQ', u'version': '1.5.0', u'copyright': 'Copyright (C) 2007-2009 LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd.', u'information': 'Licensed under the MPL. See http://www.rabbitmq.com/'}, mechanisms: ['PLAIN', 'AMQPLAIN'], locales: ['en_US'] < (10, 11): Connection.start_ok > (10, 30): Connection.tune < (10, 31): Connection.tune_ok < (10, 40): Connection.open > (10, 41): Connection.open_ok Open OK! known_hosts [elm.cozy.org:5672] TRACE: create channel using channel_id: 1 < (20, 10): Channel.open > (20, 11): Channel.open_ok Channel open TRACE: access_request < (30, 10): Channel.access_request > (30, 11): Channel.access_request_ok TRACE: make message TRACE: basic_publish < (60, 40): Channel.basic_publish TRACE: ping < (40, 10): Channel.exchange_declare > (20, 40): Channel.close < (20, 41): Channel.close_ok Closed channel #1 Traceback (most recent call last): File "bin/foo.py", line 34, in <module> ping_channel(channel) File "bin/foo.py", line 8, in ping_channel channel.exchange_declare("RANDOMTEXT",type='topic', passive=True) File "/opt/local/lib/python2.5/site-packages/amqplib/ client_0_8.py", line 1814, in exchange_declare (40, 11), # Channel.exchange_declare_ok File "/opt/local/lib/python2.5/site-packages/amqplib/ client_0_8.py", line 203, in wait return self._dispatch(method_sig, args, content) File "/opt/local/lib/python2.5/site-packages/amqplib/ client_0_8.py", line 115, in _dispatch return amqp_method(self, args) File "/opt/local/lib/python2.5/site-packages/amqplib/ client_0_8.py", line 1244, in _close raise AMQPChannelException(reply_code, reply_text, (class_id, method_id)) amqplib.client_0_8.AMQPChannelException: (404, u"NOT_FOUND - no exchange 'bogus' in vhost '/'", (60, 40), 'Channel.basic_publish') bash-3.2$ _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostI think one of the issues is that a channel close is always going to
get a response, so the embedded .wait() to get a response to hangs in a blocking state. The issue with basic_publish is that it may channel error, or it may not, and a wait() call is going to block in non-error conditions. I assume this is why basic_publish doesn't check for channel errors. It seems to me there need to be a way to set the timeout on the wait() call (w/ msec precision). In the meantime, as a work around, I'm doing a test publish when the channel is created, closing the channel, and if no exception is raised re-opening the channel. If there are any errors subsequently they don't get noticed, but this at least handles the bulk of the channel error issues. -J On Tue, Jan 27, 2009 at 1:54 PM, Ben Hyde <bhyde@...> wrote: > > On Jan 27, 2009, at 2:34 PM, Jason J. W. Williams wrote: >> >> Hi Barry, >> >> chan_send >> .basic_publish >> (msg,exchange=args.exchange,routing_key=args.routing_key) >> to an exchange that doesn't exist. > > > Sometime ago, as Dmitriy had pointed out, Matthias suggested that a > synchronous call to RabbitMQ is a good way to see if it has consumed the > frames we previously dispatched to it. And presumably that also allows > amqplib a chance to see any errors that consumption sent back. Dmitriy > suggested using declare_exchange as possible choice for a synchronous call > to the broker, and Matthias made some other suggestions. > > So in the following ping_channel does a meaningless exchange_declare. > > Jason's example of how to get basic_publish to have an error: > > On Jan 27, 2009, at 2:34 PM, Jason J. W. Williams wrote: >> >> >> ...chan_send.basic_publish(msg,exchange=args.exchange,routing_key=args.routing_key) >> to an exchange that doesn't exist. .. > > So the following code does that, followed by calling ping_channel. The > transcript below shows amqplib reporting the error as soon as it reads off > that the channel is closing. > > The source: > > #!/usr/bin/env python > import amqplib.client_0_8 as amqp > import logging > from os import environ > > def ping_channel(channel): > channel.exchange_declare("RANDOMTEXT",type='topic', passive=True) > > > if __name__ == '__main__': > logger = logging.getLogger('amqplib') > logger.addHandler(logging.StreamHandler()) > logger.setLevel(logging.DEBUG) > def trace(m): logger.debug('TRACE: ' + m) > vhost=environ.get('AMQP_USERID','/') > trace('create connection') > connection = conn = > amqp.Connection(environ.get('AMQP_SERVER','localhost'), > > userid=environ.get('AMQP_USERID','guest'), > > password=environ.get('AMQP_USERID','guest'), > virtual_host=vhost) > trace('create channel') > channel = connection.channel() > trace('access_request') > channel.access_request(vhost, active=True, write=True) > exchange_name = environ.get('AMQP_EXCHANGE','ampq.topic') > # exchange = channel.exchange_declare(exchange_name, > # > environ.get('AMQP_EXCHANGE_KIND','topic')) > trace('make message') > msg = amqp.Message("Hi there", content_type='text/plain') > trace('basic_publish') > channel.basic_publish(msg, exchange_name, > routing_key=environ.get('AMQP_ROUTING_KEY','')) > trace('ping') > ping_channel(channel) > trace('done') > > > The transcript: > bash-3.2$ env - PATH=$PATH AMQP_SERVER=192.168.1.2 AMQP_EXCHANGE=bogus > bin/foo.py > TRACE: create connection >> (10, 10): Connection.start > Start from server, version: 8.0, properties: {u'platform': 'Erlang/OTP', > u'product': 'RabbitMQ', u'version': '1.5.0', u'copyright': 'Copyright (C) > 2007-2009 LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit > Technologies Ltd.', u'information': 'Licensed under the MPL. See > http://www.rabbitmq.com/'}, mechanisms: ['PLAIN', 'AMQPLAIN'], locales: > ['en_US'] > < (10, 11): Connection.start_ok >> (10, 30): Connection.tune > < (10, 31): Connection.tune_ok > < (10, 40): Connection.open >> (10, 41): Connection.open_ok > Open OK! known_hosts [elm.cozy.org:5672] > TRACE: create channel > using channel_id: 1 > < (20, 10): Channel.open >> (20, 11): Channel.open_ok > Channel open > TRACE: access_request > < (30, 10): Channel.access_request >> (30, 11): Channel.access_request_ok > TRACE: make message > TRACE: basic_publish > < (60, 40): Channel.basic_publish > TRACE: ping > < (40, 10): Channel.exchange_declare >> (20, 40): Channel.close > < (20, 41): Channel.close_ok > Closed channel #1 > Traceback (most recent call last): > File "bin/foo.py", line 34, in <module> > ping_channel(channel) > File "bin/foo.py", line 8, in ping_channel > channel.exchange_declare("RANDOMTEXT",type='topic', passive=True) > File "/opt/local/lib/python2.5/site-packages/amqplib/client_0_8.py", line > 1814, in exchange_declare > (40, 11), # Channel.exchange_declare_ok > File "/opt/local/lib/python2.5/site-packages/amqplib/client_0_8.py", line > 203, in wait > return self._dispatch(method_sig, args, content) > File "/opt/local/lib/python2.5/site-packages/amqplib/client_0_8.py", line > 115, in _dispatch > return amqp_method(self, args) > File "/opt/local/lib/python2.5/site-packages/amqplib/client_0_8.py", line > 1244, in _close > raise AMQPChannelException(reply_code, reply_text, (class_id, method_id)) > amqplib.client_0_8.AMQPChannelException: (404, u"NOT_FOUND - no exchange > 'bogus' in vhost '/'", (60, 40), 'Channel.basic_publish') > bash-3.2$ > _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostJason J. W. Williams wrote:
> Hi Barry, > > chan_send.basic_publish(msg,exchange=args.exchange,routing_key=args.routing_key) > to an exchange that doesn't exist. I was just wrapping that in a > try/except, assuming it would raise AMQPChannelError if there was an > issue. Unfortunately, it doesn't look like basic_publish has any logic > for checking for an error. Would it make more sense to do an exchange_declare() with passive=True to check for the existence of the exchange you're going to publish to? The PyDocs for Channel.exchange_declare() say: ----------- passive: boolean do not create exchange If set, the server will not create the exchange. The client can use this to check whether an exchange exists without modifying the server state. RULE: If set, and the exchange does not already exist, the server MUST raise a channel exception with reply code 404 (not found). ------------- Barry _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostJason J. W. Williams wrote:
> It seems to me there need to be a way to set the timeout on the wait() > call (w/ msec precision). In the meantime, as a work around, I'm doing > a test publish when the channel is created, closing the channel, and > if no exception is raised re-opening the channel. If there are any > errors subsequently they don't get noticed, but this at least handles > the bulk of the channel error issues. The development version of py-amqplib has some timeout features you can play with. http://hg.barryp.org/py-amqplib-devel/ Barry _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostBen,
On Tue, Jan 27, 2009 at 5:07 PM, Ben Hyde <bhyde@...> wrote: > Is there a more appropriate venue for AMQP users to gather and puzzle > out what's what? Theoretically there should be, but in the absence of an official AMQP user list, feel free to send your questions to the place where you think they may get best answered :-) > I feel a lack of community around my attempts to > puzzle out what design patterns are good, and what AMQP expects of me. This is unfortunate - can you tell us what we need to improve to rectify this? Thx, Ben _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostHey Barry,
> > Would it make more sense to do an exchange_declare() with passive=True to > check for the existence of the exchange you're going to publish to? The I thought about declaring the exchange in the producer, but again that would be only an instantiation check. Since the class instance is long lasting, it's not something I would want to do with every basic_publish, so if by some method the exchange were to disappear after object instantiation, the app still wouldn't know until the object (and app) were torn down. -J _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
|
|
Re: Channel CostThe code below has a flaw. It worked only by virtue of dumb luck.
The ping should be changed to check for an exchange your sure exists. Passive is spec'd to close the connection if the exchange doesn't exist (which RANDOMTEXT doesn't). That failure is masked in the example because the err. r. the bogus exchange came first. On Jan 27, 2009, at 3:54 PM, Ben Hyde wrote: > > On Jan 27, 2009, at 2:34 PM, Jason J. W. Williams wrote: >> Hi Barry, >> >> chan_send >> .basic_publish >> (msg,exchange=args.exchange,routing_key=args.routing_key) >> to an exchange that doesn't exist. > > > Sometime ago, as Dmitriy had pointed out, Matthias suggested that a > synchronous call to RabbitMQ is a good way to see if it has consumed > the frames we previously dispatched to it. And presumably that also > allows amqplib a chance to see any errors that consumption sent back. > Dmitriy suggested using declare_exchange as possible choice for a > synchronous call to the broker, and Matthias made some other > suggestions. > > So in the following ping_channel does a meaningless exchange_declare. > > Jason's example of how to get basic_publish to have an error: > > On Jan 27, 2009, at 2:34 PM, Jason J. W. Williams wrote: >> ...chan_send >> .basic_publish >> (msg,exchange=args.exchange,routing_key=args.routing_key) >> to an exchange that doesn't exist. .. > > So the following code does that, followed by calling ping_channel. > The transcript below shows amqplib reporting the error as soon as it > reads off that the channel is closing. > > The source: > > #!/usr/bin/env python > import amqplib.client_0_8 as amqp > import logging > from os import environ > > def ping_channel(channel): > channel.exchange_declare("RANDOMTEXT",type='topic', passive=True) > > > if __name__ == '__main__': > logger = logging.getLogger('amqplib') > logger.addHandler(logging.StreamHandler()) > logger.setLevel(logging.DEBUG) > def trace(m): logger.debug('TRACE: ' + m) > vhost=environ.get('AMQP_USERID','/') > trace('create connection') > connection = conn = > amqp.Connection(environ.get('AMQP_SERVER','localhost'), > > userid=environ.get('AMQP_USERID','guest'), > > password=environ.get('AMQP_USERID','guest'), > virtual_host=vhost) > trace('create channel') > channel = connection.channel() > trace('access_request') > channel.access_request(vhost, active=True, write=True) > exchange_name = environ.get('AMQP_EXCHANGE','ampq.topic') > # exchange = channel.exchange_declare(exchange_name, > # > environ.get('AMQP_EXCHANGE_KIND','topic')) > trace('make message') > msg = amqp.Message("Hi there", content_type='text/plain') > trace('basic_publish') > channel.basic_publish(msg, exchange_name, > routing_key=environ.get('AMQP_ROUTING_KEY','')) > trace('ping') > ping_channel(channel) > trace('done') > > > The transcript: > bash-3.2$ env - PATH=$PATH AMQP_SERVER=192.168.1.2 AMQP_EXCHANGE=bogus > bin/foo.py > TRACE: create connection >> (10, 10): Connection.start > Start from server, version: 8.0, properties: {u'platform': 'Erlang/ > OTP', u'product': 'RabbitMQ', u'version': '1.5.0', u'copyright': > 'Copyright (C) 2007-2009 LShift Ltd., Cohesive Financial Technologies > LLC., and Rabbit Technologies Ltd.', u'information': 'Licensed under > the MPL. See http://www.rabbitmq.com/'}, mechanisms: ['PLAIN', > 'AMQPLAIN'], locales: ['en_US'] > < (10, 11): Connection.start_ok >> (10, 30): Connection.tune > < (10, 31): Connection.tune_ok > < (10, 40): Connection.open >> (10, 41): Connection.open_ok > Open OK! known_hosts [elm.cozy.org:5672] > TRACE: create channel > using channel_id: 1 > < (20, 10): Channel.open >> (20, 11): Channel.open_ok > Channel open > TRACE: access_request > < (30, 10): Channel.access_request >> (30, 11): Channel.access_request_ok > TRACE: make message > TRACE: basic_publish > < (60, 40): Channel.basic_publish > TRACE: ping > < (40, 10): Channel.exchange_declare >> (20, 40): Channel.close > < (20, 41): Channel.close_ok > Closed channel #1 > Traceback (most recent call last): > File "bin/foo.py", line 34, in <module> > ping_channel(channel) > File "bin/foo.py", line 8, in ping_channel > channel.exchange_declare("RANDOMTEXT",type='topic', passive=True) > File "/opt/local/lib/python2.5/site-packages/amqplib/ > client_0_8.py", line 1814, in exchange_declare > (40, 11), # Channel.exchange_declare_ok > File "/opt/local/lib/python2.5/site-packages/amqplib/ > client_0_8.py", line 203, in wait > return self._dispatch(method_sig, args, content) > File "/opt/local/lib/python2.5/site-packages/amqplib/ > client_0_8.py", line 115, in _dispatch > return amqp_method(self, args) > File "/opt/local/lib/python2.5/site-packages/amqplib/ > client_0_8.py", line 1244, in _close > raise AMQPChannelException(reply_code, reply_text, (class_id, > method_id)) > amqplib.client_0_8.AMQPChannelException: (404, u"NOT_FOUND - no > exchange 'bogus' in vhost '/'", (60, 40), 'Channel.basic_publish') > bash-3.2$ > > _______________________________________________ > rabbitmq-discuss mailing list > rabbitmq-discuss@... > http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss _______________________________________________ rabbitmq-discuss mailing list rabbitmq-discuss@... http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss |
| Free embeddable forum powered by Nabble | Forum Help |