# Broker status update

**URL:** <https://community.zeek.org/t/broker-status-update/4166>\
**Category:** Development\
**Tags:** development\
**Created:** [May 21, 2016, 4:01pm UTC](https://community.zeek.org/t/broker-status-update/4166 "2016-05-21T16:01:32Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Matthias\_Vallentin1](https://yyz1.discourse-cdn.com/flex011/user_avatar/community.zeek.org/matthias_vallentin1/32/596_2.png) [@Matthias\_Vallentin1](https://community.zeek.org/u/Matthias_Vallentin1)\
**Post date:** [May 21, 2016, 4:01pm UTC](https://community.zeek.org/t/broker-status-update/4166/1 "2016-05-21T16:01:32Z")

</div>

This is just a brief summary of where the Broker overhaul is currently  
at. The new Broker API will come two types of endpoints: blocking and  
nonblocking. The former provides a synchronous API to receive messages,  
whereas the latter operates fully asynchronous. Performance-wise, the  
asynchronous version has a major advantage because it does not introduce  
buffering. The callback provided upon endpoint construction will be  
immediately executed by the Broker runtime, for each message as it  
arrives. For a blocking endpoint, it's the users responsibility to  
extract messages, otherwise they queue up.

Endpoints can only be constructed through a broker::context object:

&nbsp;&nbsp;&nbsp;&nbsp;// Encapsulates global states, such as announced types, thread pool,  
&nbsp;&nbsp;&nbsp;&nbsp;// CAF scheduler, etc.  
&nbsp;&nbsp;&nbsp;&nbsp;context ctx;

&nbsp;&nbsp;&nbsp;&nbsp;// Creates a synchronous endpoint.  
&nbsp;&nbsp;&nbsp;&nbsp;auto be = ctx.spawn\<blocking\>();  
&nbsp;&nbsp;&nbsp;&nbsp;auto msg = be.receive(); // Block and wait for next message.  
&nbsp;&nbsp;&nbsp;&nbsp;be.receive(  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&](const topic&, const message&) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// As above, but use a lambda to handle the topic-message pair.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;); // Block and wait for next message.

&nbsp;&nbsp;&nbsp;&nbsp;// Creates an asynchronous endpoint.  
&nbsp;&nbsp;&nbsp;&nbsp;auto ne = ctx.spawn\<nonblocking\>(  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[=](const topic&, const message&) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// invoked for every subscribed message  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;);

Other than that, both brokers have a publish/subscribe interface, e.g.:

&nbsp;&nbsp;&nbsp;&nbsp;be.subscribe("foo");  
&nbsp;&nbsp;&nbsp;&nbsp;be.subscribe("bar");  
&nbsp;&nbsp;&nbsp;&nbsp;auto t = topic{"bar"};  
&nbsp;&nbsp;&nbsp;&nbsp;auto msg = make\_message(42, "string");  
&nbsp;&nbsp;&nbsp;&nbsp;be.publish(t, msg);

I'll post more updates as the development progresses, but all of the  
above examples are now working.

The TODO list currently includes:

&nbsp;&nbsp;&nbsp;&nbsp;- Peerings: managing subscriptions across multiple endpoints. Here's  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;an example:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Make two endpoints.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;auto x = ctx.spawn\<...\>(...);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;auto y = ctx.spawn\<...\>(...);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I'm torn between two interfaces. This is the first:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;peer(x, y); // Create a peering between the two endpoints.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;peer(y, x); // Idempotent. Peerings are symmetric.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Peer with a remote endpoint. Requires that the remote side  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// called e.listen(addr, port) beforehand.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;auto r = ctx.spawn\<remote\>("1.2.3.4", 42000);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;peer(y, r);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Undo a peering.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unpeer(x, y);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unpeer(r, y);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The second is:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.peer(y); // Create a peering between the two endpoints.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y.peer(x); // Idempotent. Peerings are symmetric.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.peer("1.2.3.4", 42000); // Peer with a remote endpoint.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.unpeer(y);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.unpeer("1.2.3.4", 42000); // Unpeer from a remote endpoint,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;must match previous peering data.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Personally, I'm favoring the first version, as the functional API  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;makes the symmetry of the peering relationship clearer.

&nbsp;&nbsp;&nbsp;&nbsp;- Data store: integrate the new "main API" with the existing data  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stores. My plan is to use as much as possible from the existing  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data store API.

&nbsp;&nbsp;&nbsp;&nbsp;- Bindings: For Python, I'm considering switching to pybind11 [1],  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;which provides a much more convenient API than SWIG and supports  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modern C++11.

Please chime in if you have questions/comment or see opportunities for  
improvement.

&nbsp;&nbsp;&nbsp;&nbsp;Matthias

[1] [http://pybind11.readthedocs.io/en/latest/classes.html](http://pybind11.readthedocs.io/en/latest/classes.html)

---

<div class="post-metadata">

**Author:** ![robin](https://yyz1.discourse-cdn.com/flex011/user_avatar/community.zeek.org/robin/32/599_2.png) [@robin](https://community.zeek.org/u/robin)\
**Post date:** [May 23, 2016, 3:23pm UTC](https://community.zeek.org/t/broker-status-update/4166/2 "2016-05-23T15:23:26Z")

</div>

> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;peer(x, y); // Create a peering between the two endpoints.  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;peer(y, x); // Idempotent. Peerings are symmetric.

> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.peer(y); // Create a peering between the two endpoints.  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y.peer(x); // Idempotent. Peerings are symmetric.

I would prefer the 2nd way for consistenct, as all the other  
operations use the method-based scheme. The idempotency seems  
secondary to that I would say.

Related question: what exactly are the semantics if only one side of  
the peering is set up?

> &nbsp;&nbsp;&nbsp;&nbsp;- Bindings: For Python, I'm considering switching to pybind11 [1],  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;which provides a much more convenient API than SWIG and supports  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modern C++11.

Hmm ... I see the appeal but it would introduce a new dependency and  
its Python-specific (I assume), whereas with SWIG it's easier to add  
more languages later. Is that worth the benefit of switching?

Robin

---

<div class="post-metadata">

**Author:** ![Matthias\_Vallentin1](https://yyz1.discourse-cdn.com/flex011/user_avatar/community.zeek.org/matthias_vallentin1/32/596_2.png) [@Matthias\_Vallentin1](https://community.zeek.org/u/Matthias_Vallentin1)\
**Post date:** [May 27, 2016, 5:35pm UTC](https://community.zeek.org/t/broker-status-update/4166/3 "2016-05-27T17:35:23Z")

</div>

> \> peer(x, y); // Create a peering between the two endpoints.  
> \> peer(y, x); // Idempotent. Peerings are symmetric.
> 
> \> x.peer(y); // Create a peering between the two endpoints.  
> \> y.peer(x); // Idempotent. Peerings are symmetric.
> 
> I would prefer the 2nd way for consistenct, as all the other  
> operations use the method-based scheme. The idempotency seems  
> secondary to that I would say.

Okay, after mulling over this a bit more, I think the second version  
makes sense also for another reason: overloads. Both of these statements  
should be valid:

&nbsp;&nbsp;&nbsp;&nbsp;x.peer("127.0.0.1", 42000);  
&nbsp;&nbsp;&nbsp;&nbsp;x.peer(y);

With a free function, this becomes not as clear anymore.

> Related question: what exactly are the semantics if only one side of  
> the peering is set up?

The peering occurs asynchronously. The function endpoint::peer returns  
void, and when the peering result (failure/success) becomes available, a  
dedicated status message will be enqueued in the endpoint's mailbox.  
This message has to be extracted via endpoint::receive, or in the  
asynchronous case, there needs to be handler for the status present  
(otherwise the message gets dropped).

> Hmm ... I see the appeal but it would introduce a new dependency and  
> its Python-specific (I assume), whereas with SWIG it's easier to add  
> more languages later. Is that worth the benefit of switching?

We already need SWIG and its Python-specific bindings, which are two  
separate packages. Since every language has its idiosyncrasies, it's  
quite unwieldy to have one framework to rule them all. At least SWIG  
feels not like a productive toolkit for modern C++.

Also, since pybind11 is a small header-only package, we can easily ship  
it directly with Broker, which would render the existing package  
dependencies obsolete. That is, we would not introducing a new  
dependency, but remove two instead ;-).

That said, this is my impression after just briefly looking at the  
bindings space. I'll perform a more thorough evaluation once I'll  
actually start delving into writing the bindings.

&nbsp;&nbsp;&nbsp;&nbsp;Matthias

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex011/uploads/zeek/original/1X/f09d732bc2cc7c7cc7e35db67cf4e1d5233ce7a7.png) [@system](https://community.zeek.org/u/system)\
**Post date:** [May 6, 2022, 3:43pm UTC](https://community.zeek.org/t/broker-status-update/4166/4 "2022-05-06T15:43:42Z")

</div>


