== The Event Bus
:toc: left

The `link:../../ceylondoc/vertx-core//eventbus/EventBus.type.html[event bus]` is the *nervous system* of Vert.x.

There is a single event bus instance for every Vert.x instance and it is obtained using the method `link:../../ceylondoc/vertx-core//Vertx.type.html#eventBus()[eventBus]`.

The event bus allows different parts of your application to communicate with each other irrespective of what language they are written in,
and whether they're in the same Vert.x instance, or in a different Vert.x instance.

It can even be bridged to allow client side JavaScript running in a browser to communicate on the same event bus.

The event bus forms a distributed peer-to-peer messaging system spanning multiple server nodes and multiple browsers.

The event bus supports publish/subscribe, point to point, and request-response messaging.

The event bus API is very simple. It basically involves registering handlers, unregistering handlers and
sending and publishing messages.

First some theory:

=== The Theory

==== Addressing

Messages are sent on the event bus to an *address*.

Vert.x doesn't bother with any fancy addressing schemes. In Vert.x an address is simply a string.
Any string is valid. However it is wise to use some kind of scheme, e.g. using periods to demarcate a namespace.

Some examples of valid addresses are +europe.news.feed1+, +acme.games.pacman+, +sausages+, and +X+.

==== Handlers

Messages are received in handlers. You register a handler at an address.

Many different handlers can be registered at the same address.

A single handler can be registered at many different addresses.

==== Publish / subscribe messaging

The event bus supports *publishing* messages.

Messages are published to an address. Publishing means delivering the message
to all handlers that are registered at that address.

This is the familiar *publish/subscribe* messaging pattern.

==== Point to point and Request-Response messaging

The event bus also supports *point to point* messaging.

Messages are sent to an address. Vert.x will then route it to just one of the handlers registered at that address.

If there is more than one handler registered at the address,
one will be chosen using a non-strict round-robin algorithm.

With point to point messaging, an optional reply handler can be specified when sending the message.

When a message is received by a recipient, and has been handled, the recipient can optionally decide to reply to
the message. If they do so the reply handler will be called.

When the reply is received back at the sender, it too can be replied to. This can be repeated ad-infinitum,
and allows a dialog to be set-up between two different verticles.

This is a common messaging pattern called the *request-response* pattern.

==== Best-effort delivery

Vert.x does it's best to deliver messages and won't consciously throw them away. This is called *best-effort* delivery.

However, in case of failure of all or parts of the event bus, there is a possibility messages will be lost.

If your application cares about lost messages, you should code your handlers to be idempotent, and your senders
to retry after recovery.

==== Types of messages

Out of the box Vert.x allows any primitive/simple type, String, or `link:../../ceylondoc/vertx-core//buffer/Buffer.type.html[buffers]` to
be sent as messages.

However it's a convention and common practice in Vert.x to send messages as http://json.org/[JSON]

JSON is very easy to create, read and parse in all the languages that Vert.x supports so it has become a kind of
_lingua franca_ for Vert.x.

However you are not forced to use JSON if you don't want to.

The event bus is very flexible and also supports sending arbitrary objects over the event bus.
You do this by defining a `codec` for the objects you want to send.

=== The Event Bus API

Let's jump into the API

==== Getting the event bus

You get a reference to the event bus as follows:

[source,ceylon]
----
value eb = vertx.eventBus();

----

There is a single instance of the event bus per Vert.x instance.

==== Registering Handlers

This simplest way to register a handler is using `link:../../ceylondoc/vertx-core//eventbus/EventBus.type.html#consumer(java.lang.String,%20io.vertx.core.Handler)[consumer]`.
Here's an example:

[source,ceylon]
----
value eb = vertx.eventBus();

eb.consumer("news.uk.sport", (Message<Object> message) {
  print("I have received a message: ``message.body()``");
});

----

When a message arrives for your handler, your handler will be called, passing in the `link:../../ceylondoc/vertx-core//eventbus/Message.type.html[message]`.

The object returned from call to +consumer()+ is an instance of `link:../../ceylondoc/vertx-core//eventbus/MessageConsumer.type.html[MessageConsumer]`

This object can subsequently be used to unregister the handler, or use the handler as a stream.

Alternatively you can use `link:../../ceylondoc/vertx-core//eventbus/EventBus.type.html#consumer(java.lang.String,%20io.vertx.core.Handler)[consumer]` to
to return a +MessageConsumer+ with no handler set, and then set the handler on that. For example:

[source,ceylon]
----
value eb = vertx.eventBus();

value consumer = eb.consumer("news.uk.sport");
consumer.handler((Message<String> message) {
  print("I have received a message: ``message.body()``");
});

----

When registering a handler on a clustered event bus, it can take some time for the registration to reach all
nodes of the cluster.

If you want to be notified when this has completed, you can register a `link:../../ceylondoc/vertx-core//eventbus/MessageConsumer.type.html#completionHandler(io.vertx.core.Handler)[completion handler]`
on the +MessageConsumer+ object.

[source,ceylon]
----
consumer.completionHandler((Throwable? res) {
  if (!exists res) {
    print("The handler registration has reached all nodes");
  } else {
    print("Registration failed!");
  };
});

----

==== Un-registering Handlers

To unregister a handler, call `link:../../ceylondoc/vertx-core//eventbus/MessageConsumer.type.html#unregister()[unregister]`.

If you are on a clustered event bus, un-registering can take some time to propagate across the nodes, if you want to
be notified when this is complete use `link:../../ceylondoc/vertx-core//eventbus/MessageConsumer.type.html#unregister(io.vertx.core.Handler)[unregister]`.

[source,ceylon]
----
consumer.unregister((Throwable? res) {
  if (!exists res) {
    print("The handler un-registration has reached all nodes");
  } else {
    print("Un-registration failed!");
  };
});

----

==== Publishing messages

Publishing a message is simple. Just use `link:../../ceylondoc/vertx-core//eventbus/EventBus.type.html#publish(java.lang.String,%20java.lang.Object)[publish]` specifying the
address to publish it to.

[source,ceylon]
----
eventBus.publish("news.uk.sport", "Yay! Someone kicked a ball");

----

That message will then be delivered to all handlers registered against the address +news.uk.sport+.

==== Sending messages

Sending a message will result in only one handler registered at the address receiving the message.
This is the point to point messaging pattern. The handler is chosen in a non-strict round-robin fashion.

You can send a message with `link:../../ceylondoc/vertx-core//eventbus/EventBus.type.html#send(java.lang.String,%20java.lang.Object)[send]`

[source,ceylon]
----
eventBus.send("news.uk.sport", "Yay! Someone kicked a ball");

----

include::override/eventbus_headers.adoc[]

==== Message ordering

Vert.x will deliver messages to any particular handler in the same order they were sent from any particular sender.

==== The Message object

The object you receive in a message handler is a `link:../../ceylondoc/vertx-core//eventbus/Message.type.html[Message]`.

The `link:../../ceylondoc/vertx-core//eventbus/Message.type.html#body()[body]` of the message corresponds to the object that was sent or published.

The headers of the message are available with `link:../../ceylondoc/vertx-core//eventbus/Message.type.html#headers()[headers]`.

==== Acknowledging messages / sending replies

When using `link:../../ceylondoc/vertx-core//eventbus/EventBus.type.html#send(java.lang.String,%20java.lang.Object)[send]` the event bus attempts to deliver the message to a
`link:../../ceylondoc/vertx-core//eventbus/MessageConsumer.type.html[MessageConsumer]` registered with the event bus.

In some cases it's useful for the sender to know when the consumer has received the message and "processed" it.

To acknowledge that the message has been processed the consumer can reply to the message by calling `link:../../ceylondoc/vertx-core//eventbus/Message.type.html#reply(java.lang.Object)[reply]`.

When this happens it causes a reply to be sent back to the sender and the reply handler is invoked with the reply.

An example will make this clear:

The receiver:

[source,ceylon]
----
value consumer = eventBus.consumer("news.uk.sport");
consumer.handler((Message<String> message) {
  print("I have received a message: ``message.body()``");
  message.reply("how interesting!");
});

----

The sender:

[source,ceylon]
----
eventBus.send("news.uk.sport", "Yay! Someone kicked a ball across a patch of grass", (Message<Object>|Throwable ar) {
  if (is Message<Object> ar) {
    print("Received reply: ``ar.body()``");
  };
});

----

The reply can contain a message body which can contain useful information.

What the "processing" actually means is application defined and depends entirely on what the message consumer does
and is not something that the Vert.x event bus itself knows or cares about.

Some examples:

* A simple message consumer which implements a service which returns the time of the day would acknowledge with a message
containing the time of day in the reply body
* A message consumer which implements a persistent queue, might acknowledge with `true` if the message was successfully
persisted in storage, or `false` if not.
* A message consumer which processes an order might acknowledge with `true` when the order has been successfully processed
so it can be deleted from the database

==== Sending with timeouts

When sending a message with a reply handler you can specify a timeout in the `link:../../ceylondoc/vertx-core//eventbus/DeliveryOptions.type.html[DeliveryOptions]`.

If a reply is not received within that time, the reply handler will be called with a failure.

The default timeout is 30 seconds.

==== Send Failures

Message sends can fail for other reasons, including:

* There are no handlers available to send the message to
* The recipient has explicitly failed the message using `link:../../ceylondoc/vertx-core//eventbus/Message.type.html#fail(int,%20java.lang.String)[fail]`

In all cases the reply handler will be called with the specific failure.

include::override/eventbus.adoc[]

==== Clustered Event Bus

The event bus doesn't just exist in a single Vert.x instance. By clustering different Vert.x instances together on
your network they can form a single, distributed, event bus.

==== Clustering programmatically

If you're creating your Vert.x instance programmatically you get a clustered event bus by configuring the Vert.x
instance as clustered;

[source,ceylon]
----
import io.vertx.ceylon.core { vertx_ = vertx } 

...

value options = VertxOptions();
vertx_.clusteredVertx(options, (Vertx|Throwable res) {
  if (is Vertx res) {
    value vertx = res;
    value eventBus = vertx.eventBus();
    print("We now have a clustered event bus: ``eventBus``");
  } else {
    print("Failed: ``res``");
  };
});

----

You should also make sure you have a `ClusterManager` implementation on your classpath,
for example the default `HazelcastClusterManager`.

==== Clustering on the command line

You can run Vert.x clustered on the command line with

 vertx run my-verticle.js -cluster

=== Automatic clean-up in verticles

If you're registering event bus handlers from inside verticles, those handlers will be automatically unregistered
when the verticle is undeployed.

== Configuring the event bus

The event bus can be configured. It is particularly useful when the event bus is clustered. Under the hood
the event bus uses TCP connections to send and receive message, so the
`link:../../ceylondoc/vertx-core//eventbus/EventBusOptions.type.html[EventBusOptions]` let you configure all aspects of these TCP connections. As
the event bus acts as a server and client, the configuration is close to
`link:../../ceylondoc/vertx-core//net/NetClientOptions.type.html[NetClientOptions]` and `link:../../ceylondoc/vertx-core//net/NetServerOptions.type.html[NetServerOptions]`.

[source,ceylon]
----
import io.vertx.ceylon.core { vertx_ = vertx } 
import io.vertx.ceylon.core.http { required } 

...

value options = VertxOptions {
  eventBusOptions = EventBusOptions {
    ssl = true;
    keyStoreOptions = JksOptions {
      path = "keystore.jks";
      password = "wibble";
    };
    trustStoreOptions = JksOptions {
      path = "keystore.jks";
      password = "wibble";
    };
    clientAuth = "REQUIRED";
  };
};

vertx_.clusteredVertx(options, (Vertx|Throwable res) {
  if (is Vertx res) {
    value vertx = res;
    value eventBus = vertx.eventBus();
    print("We now have a clustered event bus: ``eventBus``");
  } else {
    print("Failed: ``res``");
  };
});

----

The previous snippet depicts how you can use SSL connections for the event bus, instead of plain TCP
connections.

**WARNING**: to enforce the security in clustered mode, you **must** configure the
cluster manager to use encryption or enforce security. Refer to the documentation of the cluster
manager for further details.

The event bus configuration needs to be consistent in all the cluster nodes.

The `link:../../ceylondoc/vertx-core//eventbus/EventBusOptions.type.html[EventBusOptions]` also lets you specify whether or not the event bus is
clustered, the port and host, as you would do with `link:../../ceylondoc/vertx-core//VertxOptions.type.html#setClustered(boolean)[clustered]`,
 `link:../../ceylondoc/vertx-core//VertxOptions.type.html#getClusterHost()[getClusterHost]` and `link:../../ceylondoc/vertx-core//VertxOptions.type.html#getClusterPort()[getClusterPort]`.

When used in containers, you can also configure the public host and port:

[source,ceylon]
----
import io.vertx.ceylon.core { vertx_ = vertx } 

...

value options = VertxOptions {
  eventBusOptions = EventBusOptions {
    clusterPublicHost = "whatever";
    clusterPublicPort = 1234;
  };
};

vertx_.clusteredVertx(options, (Vertx|Throwable res) {
  if (is Vertx res) {
    value vertx = res;
    value eventBus = vertx.eventBus();
    print("We now have a clustered event bus: ``eventBus``");
  } else {
    print("Failed: ``res``");
  };
});

----