Here is another fun nuance to think about regarding min-bus. Should there be a difference between a connection between plugins a
and b
and between b
and a
? Under the current draft, these are indeed different, and both can coexist at the same time. It is difficult for plugins to ensure that there is only one connection between them, because of race conditions where both might simultaneously open a connection to the other one. It's possible to work around that, but both plugins need to cooperate. And to at least one of the plugins, it would look like its connection attempt failed. So here are two alternative approaches: An asymmetric one, and a symmetric one.
The asymmetric approach is done through a tiny yet fundamental change: When plugin a
wants to connect to plugin b
, the server never tells b
about the identity of a
. Under this model, the receiving side of a plugin is fully passive and must treat all incoming connections the same way. This actually simplifies plugin implementation, as there are fewer decisions to make. A plugin just offers some services to the outside world (not caring about who consumes them), and it can anonymously consume the services offered by other plugins. Proactive and reactive behavior are neatly separated. There's no need to think about consolidating connections a -> b
and b -> a
, because it's impossible for the plugins to detect anyways.
For the alternative, symmetric approach, the server takes an active role in race conditions where both plugins want to start a connection to the other one concurrently. Suppose a
tells the server that it wants to connect to b
. The server opens the appropriate duplex to b
, but then the server receives b
's wish for a connection to a
, which b
has sent before the server contacted it about a
's connection establishment attempt. Under the current min-bus draft, the server does not care and simply relays b
's connection attempt. But instead, the server tells a
that its connection attempt succeeded, and it also tells b
the same. Now,b
still got that connection attempt from a
, so what happens to that? It was received by b
after b
sent out its own connection attempt, so b
has all the necessary knowledge to just silently discard it. The actual plugin code of b
never gets notified of a
's connection attempt. There are some more details regarding credit and heartbeats, but overall that's how the symmetric approach would work.
With the symmetric approach, the server must only allow a single connection between two plugins at a time, no matter which one initiated it. When a race condition occurs, each of the plugins thinks its own connection attempt succeeded. So in general, plugins can not rely on the information of who initiated the connection.
So these are the three different options, and none of them are strictly better than the others. You have to accept one of:
- plugins not knowing who connected to them
- plugins not knowing which of the two initiated the connection
- race conditions upon simultaneous connection attempts
I haven't even made up my mind on whether anonymous service consumers are a drawback, or actually the better model (in which case the asymmetric approach would be actually superior to the other ones).