Standalone Event Dispatcher

From @mattbennett on Mon Aug 14 2017 12:50:03 GMT+0000 (UTC)

Hi Geoff,

Thanks :grinning:

Your code is valid, but perhaps isn’t the best way of achieving your goal. Events are intended to be dispatched from an originating service, and handled in any “interested” subscribing services. The standalone dispatcher is a helper for “faking” that behaviour when needed (e.g. in tests) or to originate events from non-nameko services.

The code above will send a “ping” event claiming to originate from a “monitor” service. It is valid, but breaks the (implicit and undocumented!) intention that events are sourced at real services.

Assuming the aim is to get all services to do something when the “status” command is issued in slack, I would do it by dropping down to the lower-level “messaging” extensions that events are built on top of.

Nameko events are little more than a particular configuration of underlying elements of AMQP (the exchanges, queues, bindings, routing keys and consumers). For your use-case you probably want to configure these elements slightly differently.

I guess you want a single exchange that all services bind a queue to, and a consumer in each service instance. This is basically what you get with broadcast events, but doing it yourself you can control the exchange name, routing keys and queue names.

Something like this:

# slackbot
from nameko.messaging import Publisher
from kombu.messaging import Exchange

monitoring_exchange = Exchange(name="monitoring")

class Slack:
    name = 'slackbot'
    config = Config()

    publish = Publisher(exchange=monitoring_exchange)

    @rtm.handle_message('status')
    def on_status(self, event, message):
        self.publish(routing_key="ping", event['channel'])
# service_x.py
from nameko.messaging import consume
from kombu.messaging import Exchange, Queue

monitoring_exchange = Exchange(name="monitoring")

ping_queue = Queue(name="<unique-name>", routing_key="ping", exchange="monitoring")

class Service:
    name = "x"

    @consume(queue=ping_queue)
    def handle_ping(self, payload):
        pass

1 Like