docs(bpapi): Add README
This commit is contained in:
parent
48366a80c8
commit
1e795759ce
|
@ -0,0 +1,109 @@
|
|||
Backplane API
|
||||
===
|
||||
|
||||
# Motivation
|
||||
|
||||
This directory contains modules that help defining and maintaining
|
||||
EMQX broker-to-broker (backplane) protocols.
|
||||
|
||||
Historically, all inter-broker communication was done by the means of
|
||||
remote procedure calls. This approach allowed for rapid development,
|
||||
but presented some challenges for rolling cluster upgrade, since
|
||||
tracking destination of the RPC could not be automated using standard
|
||||
tools (such as xref and dialyzer).
|
||||
|
||||
Starting from EMQX v5.0.0, `emqx_bpapi` sub-application is used to
|
||||
facilitate backplane API backward- and forward-compatibility. Wild
|
||||
remote procedure calls are no longer allowed. Instead, every call is
|
||||
decorated by a very thin wrapper function located in a versioned
|
||||
"_proto_" module.
|
||||
|
||||
Some restrictions are put on the lifecycle of the `_proto_` modules,
|
||||
and they are additionally tracked in a database created in at the
|
||||
build time.
|
||||
|
||||
# Rolling upgrade
|
||||
|
||||
During rolling upgrades different versions of the code is running
|
||||
side-by-side:
|
||||
|
||||
```txt
|
||||
+--------------+ +---------------+
|
||||
| | | |
|
||||
| Node A | ----- rpc:call(foo, foo, []) ------> | Node B |
|
||||
| | | |
|
||||
| EMQX 5.1.2 | <---- rpc:call(foo, foo, [1]) ------- | EMQX 5.0.13 |
|
||||
| | | |
|
||||
+--------------+ +---------------+
|
||||
```
|
||||
|
||||
The following changes will break the backplane API:
|
||||
|
||||
1. removing a target function
|
||||
2. adding a new method to the protocol
|
||||
3. reducing the domain of the target function
|
||||
4. extending the co-domain of the target function
|
||||
|
||||
Bullets 1 and 2 are addressed by a static check that verifies
|
||||
immutability of the proto modules. 3 is checked using dialyzer
|
||||
specs. 4 is not checked at this moment.
|
||||
|
||||
# Backplane API modules
|
||||
|
||||
A distributed Erlang application in EMQX is organized like this:
|
||||
|
||||
```txt
|
||||
...
|
||||
myapp/src/myapp.erl
|
||||
myapp/src/myapp.app.src
|
||||
myapp/src/proto/myapp_proto_v1.erl
|
||||
myapp/src/proto/myapp_proto_v2.erl
|
||||
```
|
||||
|
||||
Notice `proto` directory containing several modules that follow
|
||||
`<something>_proto_v<number>` pattern.
|
||||
|
||||
These modules should follow the following template:
|
||||
|
||||
```erlang
|
||||
-module(emqx_proto_v1).
|
||||
|
||||
-behaviour(emqx_bpapi).
|
||||
|
||||
%% Note: the below include is mandatory
|
||||
-include_lib("emqx/include/bpapi.hrl").
|
||||
|
||||
-export([ introduced_in/0
|
||||
, deprecated_since/0 %% Optional
|
||||
]).
|
||||
|
||||
-export([ is_running/1
|
||||
]).
|
||||
|
||||
introduced_in() ->
|
||||
"5.0.0".
|
||||
|
||||
deprecated_since() ->
|
||||
"5.2.0".
|
||||
|
||||
-spec is_running(node()) -> boolean().
|
||||
is_running(Node) ->
|
||||
rpc:call(Node, emqx, is_running, []).
|
||||
```
|
||||
|
||||
The following limitations apply to these modules:
|
||||
|
||||
1. Once the minor EMQX release stated in `introduced_in()` callback of
|
||||
a module reaches GA, the module is frozen. No changes are allowed
|
||||
there, except for adding `deprecated_since()` callback.
|
||||
2. After the _next_ minor release after the one deprecating the
|
||||
module reaches GA, the module can be removed.
|
||||
3. Old versions of the protocol can be dropped in the next major
|
||||
release.
|
||||
|
||||
This way we ensure each minor EMQX release is backward-compatible with
|
||||
the previous one.
|
||||
|
||||
# Protocol version negotiation
|
||||
|
||||
TODO
|
Loading…
Reference in New Issue