Usage

To use py-emit in a project

step 1. Import pyemit

from pyemit import emit

step 2. Register events

pyemit provides both annotation based registering and direct registering. Annotation can be used if the handler is not a class method.

Be noticed that the handler MUST be a coroutine function.

from pyemit import emit
@emit.on('event_name')
async def handler(msg):
    pass

or, if it’s a class method, use emit.register instead:

from pyemit import emit
class Foo:
    async def bar(self, msg):
        pass

foo = Foo()
emit.register('event_name', foo.bar)

To know what causes the difference, please refer to $todo

step 3. Start the message pumping

you can start a local message pump by:

from pyemit import emit
async def init():
    await emit.start()

Or, if you’re prefer a remote message server, use this:

from pyemit import emit
# aioredis is required. You can install it by running `pip install aioredis>=1.3.1
async def init(dsn):
    await emit.start(emit.Engine.REDIS, dsn=dsn)

step 4. Fire and consume events

Now you can fire and consume events. To emit a message, running:

from pyemit import emit
async def foo():
    # construct msg
    msg = {}
    await emit.emit('event_name', msg)

You can fire an event without providing any message. By doing so, be sure provide no parameter to the handler. The msg must be and dict and is json serializable.

Troubeshooting

You can enable heartbeat when using REDIS engine:

from pyemit import emit
async def init(dsn):
    await emit.start(emit.Engine.REDIS, dsn=dsn, heart_beat=1)

and set logging level to DEBUG, this should print a heart beat msg every 1 second. If not seen, then check your configurations and Redis setup.

Advanced topic

RPC call

from pyemit import emit as e
from pyemit.remote import Remote

class Sum(Remote):
    def __init__(self, to_be_sum):
        super().__init__()
        self.to_be_sum = to_be_sum

    async def server_impl(self, *args, **kwargs):
        result = sum(self.to_be_sum)
        await super().respond(result)

async def test_rpc():
    await e.start(e.Engine.REDIS, dsn="redis://localhost")
    foo = Sum([0, 1, 2])
    response = await foo.invoke()
    assert response == 3

step 1. Subclass from Remote, and implement Remote.server_impl method. This one is supposed to be executed on the server side. When calculation is done, then call super().respond() to send the result back to client

step 2. At client side, create instance of the subclass you defined (i.e., foo in the example), then by calling await foo.invoke() you will get what you want.

pass parameters during construct of Remote object if any, they can be access at server side by self object.

stop the message pump

call emit.stop to stop the whole machine. call emit.unsubscribe to remove a handler.