Przeglądaj źródła

feat(bpapi): Introduce bpapi behavior

k32 4 lat temu
rodzic
commit
4f3f938d71

+ 9 - 3
apps/emqx/src/bpapi/emqx_bpapi.erl

@@ -15,9 +15,7 @@
 %%--------------------------------------------------------------------
 -module(emqx_bpapi).
 
--export_type([var_name/0, call/0, rpc/0, bpapi_meta/0, semver/0]).
-
--type semver() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}.
+-export_type([var_name/0, call/0, rpc/0, bpapi_meta/0]).
 
 -type api() :: atom().
 -type api_version() :: non_neg_integer().
@@ -31,3 +29,11 @@
          , calls   := [rpc()]
          , casts   := [rpc()]
          }.
+
+-callback introduced_in() -> string().
+
+-callback deprecated_since() -> string().
+
+-callback bpapi_meta() -> bpapi_meta().
+
+-optional_callbacks([deprecated_since/0]).

+ 7 - 29
apps/emqx/src/bpapi/emqx_bpapi_trans.erl

@@ -30,8 +30,6 @@
         { api              :: atom()
         , module           :: atom()
         , version          :: non_neg_integer() | undefined
-        , introduced_in    :: emqx_bpapi:semver() | undefined
-        , deprecated_since :: emqx_bpapi:semver() | undefined
         , targets = []     :: [{semantics(), emqx_bpapi:call(), emqx_bpapi:call()}]
         , errors = []      :: [string()]
         , file
@@ -39,10 +37,6 @@
 
 format_error(invalid_name) ->
     "BPAPI module name should follow <API>_proto_v<number> pattern";
-format_error(invalid_introduced_in) ->
-    "-introduced_in attribute should be present and its value should be a semver string";
-format_error(invalid_deprecated_since) ->
-    "value of -deprecated_since attribute should be a semver string";
 format_error({invalid_fun, Name, Arity}) ->
     io_lib:format("malformed function ~p/~p. "
                   "BPAPI functions should have exactly one clause "
@@ -68,24 +62,18 @@ go({attribute, Line, module, Mod}, S) ->
         {ok, API, Vsn} -> S#s{api = API, version = Vsn, module = Mod};
         error          -> push_err(Line, invalid_name, S)
     end;
-go({attribute, _Line, introduced_in, Str}, S) ->
-    case is_list(Str) andalso parse_semver(Str) of
-        {ok, Vsn} -> S#s{introduced_in = Vsn};
-        error     -> S %% Don't report error here, it's done in check/1
-    end;
-go({attribute, Line, deprecated_since, Str}, S) ->
-    case is_list(Str) andalso parse_semver(Str) of
-        {ok, Vsn} -> S#s{deprecated_since = Vsn};
-        error     -> push_err(Line, invalid_deprecated_since, S)
-    end;
+go({function, _Line, introduced_in, 0, _}, S)  ->
+    S;
+go({function, _Line, deprecated_since, 0, _}, S)  ->
+    S;
 go({function, Line, Name, Arity, Clauses}, S) ->
     analyze_fun(Line, Name, Arity, Clauses, S);
 go(_, S) ->
     S.
 
-check(#s{errors = Err0, introduced_in = II}) ->
-    [{none, invalid_introduced_in} || II =:= undefined] ++
-        Err0.
+check(#s{errors = Err}) ->
+    %% Post-processing checks can be placed here
+    Err.
 
 finalize(Forms, S) ->
     {Attrs, Funcs} = lists:splitwith(fun is_attribute/1, Forms),
@@ -191,16 +179,6 @@ push_err(Line, Err, S = #s{errors = Errs}) ->
 push_target(Target, S = #s{targets = Targets}) ->
     S#s{targets = [Target|Targets]}.
 
-
--spec parse_semver(string()) -> {ok, emqx_bpapi:semver()}
-                              | error.
-parse_semver(Str) ->
-    Opts = [{capture, all_but_first, list}],
-    case re:run(Str, "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$", Opts) of
-        {match, [A, B, C]} -> {ok, {list_to_integer(A), list_to_integer(B), list_to_integer(C)}};
-        nomatch            -> error
-    end.
-
 -spec api_and_version(module()) -> {ok, emqx_bpapi:api(), emqx_bpapi:version()} | error.
 api_and_version(Module) ->
     Opts = [{capture, all_but_first, list}],

+ 6 - 2
apps/emqx/src/proto/emqx_broker_proto_v1.erl

@@ -16,15 +16,19 @@
 
 -module(emqx_broker_proto_v1).
 
--introduced_in("5.0.0").
+-behaviour(emqx_bpapi).
 
--export([ forward/3
+-export([ introduced_in/0
+        , forward/3
         , forward_async/3
         ]).
 
 -include("bpapi.hrl").
 -include("emqx.hrl").
 
+introduced_in() ->
+    "5.0.0".
+
 -spec forward(node(), emqx_types:topic(), emqx_types:delivery()) -> emqx_types:deliver_result().
 forward(Node, Topic, Delivery = #delivery{}) when is_binary(Topic) ->
     emqx_rpc:call(Topic, Node, emqx_broker, dispatch, [Topic, Delivery]).