Example #1
0
    def __init__(self, messaging, agent):
        log.Logger.__init__(self, messaging)
        self._messaging = messaging
        self._sink = IChannelSink(agent)

        self._bindings = []
        self._queue = None
        self._disconnected = False
        self._consume_deferred = None

        self._queue_name = agent.get_agent_id()

        self.log_name = self._queue_name
Example #2
0
 def __init__(self, backend, agent):
     log.Logger.__init__(self, backend)
     self._backend = IBackend(backend)
     self._sink = IChannelSink(agent)
     self._channel_id = self._sink.get_agent_id()
     backend._register_channel(self)
Example #3
0
class Channel(log.Logger):

    implements(IChannel)

    channel_type = CHANNEL_TYPE

    support_broadcast = False

    def __init__(self, backend, agent):
        log.Logger.__init__(self, backend)
        self._backend = IBackend(backend)
        self._sink = IChannelSink(agent)
        self._channel_id = self._sink.get_agent_id()
        backend._register_channel(self)

    @property
    def channel_id(self):
        return self._channel_id

    ### IChannel ###

    def release(self):
        self._backend._release_channel(self)

    def post(self, recipients, message):
        if not isinstance(message, BaseMessage):
            raise ValueError("Expected second argument to be "
                             "f.a.b.BaseMessage, got %r instead"
                             % (type(message), ))

        if IDialogMessage.providedBy(message):
            reply_to = message.reply_to
            if reply_to is None:
                reply_to = recipient.Recipient(self._sink.get_agent_id(),
                                               self._backend.route,
                                               self.channel_type)
                message.reply_to = reply_to
            elif ((reply_to.type is not RecipientType.agent)
                   or (reply_to.channel != self.channel_type)):
                self.error("Invalid reply_to for tunneling, "
                           "dropping %d instance(s) of message: %r",
                           len(list(IRecipients(recipients))), message)
                return

        return self._backend.post(recipients, message)

    def bind(self, key, route=None):
        return None

    def get_bindings(self, route=None):
        return []

    def get_recipient(self):
        return recipient.Recipient(self._channel_id,
                                   self._backend.route,
                                   self._backend.channel_type)

    ### protected ###

    def initiate(self):
        return defer.succeed(self)

    def _dispatch(self, message):
        self._sink.on_message(message)
Example #4
0
class Connection(log.Logger):

    implements(IMessagingClient, IChannel)

    support_broadcast = True

    def __init__(self, messaging, agent):
        log.Logger.__init__(self, messaging)
        self._messaging = messaging
        self._sink = IChannelSink(agent)

        self._bindings = []
        self._queue = None
        self._disconnected = False
        self._consume_deferred = None

        self._queue_name = agent.get_agent_id()

        self.log_name = self._queue_name

    def initiate(self):
        d = defer.succeed(None)
        if self._queue_name is not None:
            d.addCallback(defer.drop_param,
                          self._messaging.define_queue, self._queue_name)
            d.addCallback(self._main_loop)
        else:
            self.warning('Queue name is None, skipping creating queue '
                         'and consumer.')
        d.addCallback(defer.override_result, self)
        return d

    ### IMessagingClient ###

    def disconnect(self):
        warnings.warn("IMessagingClient's diconnect() is deprecated, "
                      "please use IChannel's release() instead.",
                      DeprecationWarning)
        return self.release()

    def personal_binding(self, key, shard=None):
        warnings.warn("IMessagingClient's personal_binding() is deprecated, "
                      "please use IChannel's bind() instead.",
                      DeprecationWarning)
        return self.bind(key, shard)

    def publish(self, key, shard, message):
        warnings.warn("IMessagingClient's publish() is deprecated, "
                      "please use IChannel's post() instead.",
                      DeprecationWarning)
        return self.post(recipient.Recipient(key=key, route=shard), message)

    ### IChannel ###

    @property
    def channel_type(self):
        return self._messaging.channel_type

    def post(self, recipients, message):
        if not isinstance(message, BaseMessage):
            raise ValueError("Expected second argument to be "
                             "f.a.b.BaseMessage, got %r instead"
                             % (type(message), ))

        recipients = recipient.IRecipients(recipients)

        if IDialogMessage.providedBy(message):
            reply_to = message.reply_to
            if reply_to is None:
                reply_to = recipient.Recipient(self._queue_name,
                                               self._sink.get_shard_id(),
                                               self.channel_type)
                message.reply_to = reply_to
            elif reply_to.channel != self.channel_type:
                self.error("Invalid reply_to for messaging backend, "
                           "dropping %d instance(s) of message: %r",
                           len(list(recipients)), message)
                return

        defers = []
        for recip in recipients:
            assert recip.channel == self.channel_type, \
                   "Unexpected channel type"
            self.log('Sending message to %r', recip)
            d = self._messaging.publish(recip.key, recip.route, message)
            defers.append(d)
        return defer.DeferredList(defers)

    def release(self):
        self._disconnected = True
        if self._consume_deferred and not self._consume_deferred.called:
            ex = FinishConnection("Disconnecting")
            self._consume_deferred.errback(ex)
        return self._messaging.disconnect()

    def bind(self, key, route=None):
        if not route:
            route = self._sink.get_shard_id()
        recip = recipient.Recipient(key=key, route=route)
        return PersonalBinding(self, self._queue_name, recip)

    def get_bindings(self, route=None):
        if route is None:
            return list(self._bindings)
        return [x for x in self._bindings if x.recipient.route == route]

    def get_recipient(self):
        return recipient.Recipient(self._queue_name,
                                   self._sink.get_shard_id())

    ### protected ###

    def _register_binding(self, binding):
        self._bindings.append(binding)

    def _revoke_binding(self, binding):
        self._bindings.remove(binding)

    def _define_exchange(self, route, exchange_type="direct"):
        return self._messaging.define_exchange(route, exchange_type)

    def _create_binding(self, recipient, queue_name):
        return self._messaging.create_binding(recipient.route,
                                              recipient.key,
                                              queue_name)

    def _delete_binding(self, recipient, queue_name):
        return self._messaging.delete_binding(recipient.route,
                                              recipient.key,
                                              queue_name)

    ### private ###

    def _main_loop(self, queue):
        self._queue = queue

        def rebind(_):
            reactor.callLater(0, bind)

        def stop(reason):
            if reason.check(FinishConnection):
                self.log('Error handler: exiting, reason %r' % reason)
            else:
                reason.raiseException()

        def bind():
            if self._disconnected:
                return
            d = self._consume_queue(queue)
            d.addCallbacks(rebind, stop)

        bind()

    def _consume_queue(self, queue):

        def get_and_call_on_message(message):
            return self._sink.on_message(message)

        self._consume_deferred = queue.get()
        self._consume_deferred.addCallback(get_and_call_on_message)
        return self._consume_deferred