def __init__(self, id, outgoing): self.id = id self.outgoing = outgoing self.incoming = TimeoutDeferredQueue() self.responses = TimeoutDeferredQueue() self.queue = None self.closed = False self.reason = None
class AMQChannel(object): def __init__(self, id, outgoing): self.id = id self.outgoing = outgoing self.incoming = TimeoutDeferredQueue() self.responses = TimeoutDeferredQueue() self.queue = None self.closed = False self.reason = None def close(self, reason): if self.closed: return self.closed = True self.reason = reason self.incoming.close() self.responses.close() def dispatch(self, frame, work): payload = frame.payload if isinstance(payload, Method): if payload.method.response: self.queue = self.responses else: self.queue = self.incoming work.put(self.incoming) self.queue.put(frame) @defer.inlineCallbacks def invoke(self, method, args, content = None): if self.closed: raise Closed(self.reason) frame = Frame(self.id, Method(method, *args)) self.outgoing.put(frame) if method.content: if content == None: content = Content() self.writeContent(method.klass, content, self.outgoing) try: # here we depend on all nowait fields being named nowait f = method.fields.byname["nowait"] nowait = args[method.fields.index(f)] except KeyError: nowait = False try: if not nowait and method.responses: msg = yield self.responses.get() resp = msg.payload # There might be a problem if we have more than one command # with nowait=False running in the same time. # The order RabbitMQ server sends responses is undefined. # If the response for second request comes first we would # end up in ValueError being raised. # This is dirty hack: check that we get what we want and # remove message to the queue otherwise. # Moreover I don't quite understand the while resp.method not in method.responses: self.responses.put(msg) # More explanation is given by uncommening the print statement: # print "Expected: %r, Got: %r" %\ # (method.responses, resp.method, ) # Results I obtained in situation which would fail: #Expected: [Method(name=consume-ok, id=21)], Got: Method(name=declare-ok, id=11) #Expected: [Method(name=bind-ok, id=21)], Got: Method(name=consume-ok, id=21) msg = yield self.responses.get() resp = msg.payload if resp.method.content: content = yield readContent(self.responses) else: content = None if resp.method in method.responses: defer.returnValue(Message(resp.method, resp.args, content)) else: # With the hack above we should never go into # this branch. # If something is messed up we will end up # in never firing Deferred. For this reason # this is more a hack than the actual solution. raise ValueError(resp) except QueueClosed, e: if self.closed: raise Closed(self.reason) else: raise e