Skip to content

A library and framework for event-driven application development

License

Notifications You must be signed in to change notification settings

shiroyuki/vireo

Repository files navigation

Vireo

A library and framework for event-driven application development

Caution: This library is currently under active development. Until version 1.0, the API signatures are subject to change. While the code should be stable (not easily throwing exceptions) even before reaching version 1.0, version pinning is highly recommended.

Prerequisites

Software or library Minimum supported version Extensively tested version
Python (cpython) 3.5 3.5 for MacOS, Debian, and Fedora
pika 0.10 0.10 for MacOS, Debian, and Fedora
RabbitMQ 3.6 3.6 supplied via Docker

Future supports

Only if anyone happens to be interested in using it with

  • Amazon Kinesis Stream
  • Apache Kafka

Introduction

Vireo is a simple library and framework for event-driven applications to stop the classic DRY problem and enable developers to focus on developing applications rather than setting up the base code. There are two modes: a write-only Vireo, called Core (vireo.Core), and a read-write Vireo, called Observer (vireo.Observer which is a subclass of vireo.Core).

The design is inspired by Node.js event API.

Features

  • Simplify event-driven application development.
  • Provide the delayed message handling.

The delayed message handling is heavily relying on dead letter exchange (DLX) when Vireo is used with RabbitMQ.

Roadmap (Soon to be implemented):

  • the factory class to simplify the setup for either an emitter or an observer.

Getting started

You can simply write.

from vireo                  import Observer # or Core
from vireo.drivers.rabbitmq import Driver
from vireo.observer         import SYNC_START

# Instantiate the observer
driver = Driver('amqp://guest:guest@localhost:5672/%2F')
app    = Observer(driver) # or Core(driver)

# ... Bind event handlers ...

# Waiting all handlers to stop (only for a observer).
app.join(SYNC_START) # ASYNC_START (for non-blocking join)

APIs

vireo.Core.emit(event_name, data = None, options = None)

Emit a message to the given event.

app.emit('security.alert.intrusion', {'ip': '127.0.0.1'})

vireo.Observer.on(event_name, callback)

Listen to a direct event with a callback function.

The callback is a callable object, e.g., function, class method, lambda object, which takes only one parameter which is a JSON-decoded object.

def on_foo(self, message):
    print('on_foo:', message)

app.on('foo', on_foo)
app.on('foo.lambda', lambda x: print('foo_lambda:', x))

vireo.Observer.on_broadcast(event_name, callback)

Listen to a broadcasted event with a callback function.

The callback is a callable object, e.g., function, class method, lambda object, which takes only one parameter which is a JSON-decoded object.

def on_bar(self, message):
    print('on_bar:', message)

app.on_broadcast('bar', on_foo)
app.on_broadcast('bar.lambda', lambda x: print('bar_lambda:', x))

vireo.Observer.stop()

Send the signal to all handlers to stop observation.

NOTE: This method does not block the caller thread while waiting all handlers to stop.

app.stop()

vireo.Observer.join(running_mode = vireo.observer.SYNC_START)

Wait for all handlers to stop.

There are two mode: synchronous (vireo.observer.SYNC_START) and asynchronous (vireo.observer.ASYNC_START) joins.

app.start(ASYNC_START)

Try it out?

In the spirit of getting people started earlier, there is a sample code implemented as part of the source code (but it is never enabled by default.) However, the sample code is only working with Python 3.5 or newer due to one of the development-only requirements.

If you want to see and play with it, you can start by first cloning or downloading this source code. Here is how you can clone this.

git clone [email protected]:shiroyuki/vireo.git

Then, install Gallium Framework by running this command.

pip3 install gallium

Run the sample observer

To run, execute g3 sample.observe -d -b amqp://guest:guest@localhost:5672/%2F where RabbitMQ is running from the local host.

This command will automatically create one exchange:

  • fallback/vireo.sample.primary/vireo.sample.primary.delegated

This command will also automatically create three queues (event queues):

  • vireo.sample.primary with no listeners, 5-second message TTL and DLX to the created exchange,
  • vireo.sample.primary.delegated bound to the created exchange with one echo-only listener,
  • vireo.sample.secondary with one echo-only listener.

Emit an event

To emit an event, run g3 event.emit -d -b amqp://guest:guest@localhost:5672/%2F EVENT_NAME JSON_DATA.

For example,

g3 event.emit -d -b amqp://guest:guest@localhost:5672/%2F vireo.sample.secondary "{ \"id\": 12345 }"