Exemplo n.º 1
0
    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
Exemplo n.º 2
0
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