diff --git a/priv/grpcbox_service_bhvr.erl b/priv/grpcbox_service_bhvr.erl index 3dc03cc..8f3dbb5 100644 --- a/priv/grpcbox_service_bhvr.erl +++ b/priv/grpcbox_service_bhvr.erl @@ -8,8 +8,11 @@ -module({{module_name}}_bhvr). {{#methods}} -%% @doc {{^input_stream}}{{^output_stream}}Unary RPC{{/output_stream}}{{/input_stream}} -callback {{method}}({{^input_stream}}{{#output_stream}}{{pb_module}}:{{input}}(), grpcbox_stream:t(){{/output_stream}}{{/input_stream}}{{#input_stream}}{{^output_stream}}reference(), grpcbox_stream:t(){{/output_stream}}{{#output_stream}}reference(), grpcbox_stream:t(){{/output_stream}}{{/input_stream}}{{^input_stream}}{{^output_stream}}ctx:ctx(), {{pb_module}}:{{input}}(){{/output_stream}}{{/input_stream}}) -> - {{#output_stream}}ok{{/output_stream}}{{^output_stream}}{ok, {{pb_module}}:{{output}}(), ctx:ctx()}{{/output_stream}} | grpcbox_stream:grpc_error_response(). + {{#output_stream}}ok{{/output_stream}}{{^output_stream}}{ok, {{pb_module}}:{{output}}(), ctx:ctx()}{{/output_stream}}{{#output_stream}} | {continue, grpcbox_stream:t()}{{/output_stream}} | grpcbox_stream:grpc_error_response(). {{/methods}} + +-callback init(grpcbox_stream:t()) -> grpcbox_stream:t(). +-callback handle_info(any(), grpcbox_stream:t()) -> grpcbox_stream:t(). +-optional_callbacks([init/1, handle_info/2]). diff --git a/priv/grpcbox_service_client.erl b/priv/grpcbox_service_client.erl index 16e56a2..372f5db 100644 --- a/priv/grpcbox_service_client.erl +++ b/priv/grpcbox_service_client.erl @@ -24,7 +24,6 @@ unmarshal_fun=?UNMARSHAL_FUN(Output)}). {{#methods}} -%% @doc {{^input_stream}}{{^output_stream}}Unary RPC{{/output_stream}}{{/input_stream}} -spec {{method}}({{^input_stream}}{{pb_module}}:{{input}}(){{/input_stream}}) -> {{^output_stream}}{{^input_stream}}{ok, {{pb_module}}:{{output}}(), grpcbox:metadata()}{{/input_stream}}{{#input_stream}}{ok, grpcbox_client:stream()}{{/input_stream}}{{/output_stream}}{{#output_stream}}{{^input_stream}}{ok, grpcbox_client:stream()}{{/input_stream}}{{#input_stream}}{ok, grpcbox_client:stream()}{{/input_stream}}{{/output_stream}} | grpcbox_stream:grpc_error_response() | {error, any()}. {{method}}({{^input_stream}}Input{{/input_stream}}) -> diff --git a/rebar.config b/rebar.config index c6cc476..abdbf48 100644 --- a/rebar.config +++ b/rebar.config @@ -1,3 +1,3 @@ {erl_opts, [debug_info]}. -{deps, [{gpb, "~> 4.11"}, - {providers, "~> 1.8"}]}. +{deps, [{gpb, "~> 4.13.0"} +]}. diff --git a/rebar.lock b/rebar.lock index e6d0d0c..0e24d0d 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,14 +1,6 @@ -{"1.2.0", -[{<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},1}, - {<<"gpb">>,{pkg,<<"gpb">>,<<"4.11.2">>},0}, - {<<"providers">>,{pkg,<<"providers">>,<<"1.8.1">>},0}]}. +{"1.1.0", +[{<<"gpb">>,{pkg,<<"gpb">>,<<"4.13.0">>},0}]}. [ {pkg_hash,[ - {<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}, - {<<"gpb">>, <<"A2C05241408310B8BD8DBDFD5E1A419799E45FC1408371EAA0F595023C3B21AA">>}, - {<<"providers">>, <<"70B4197869514344A8A60E2B2A4EF41CA03DEF43CFB1712ECF076A0F3C62F083">>}]}, -{pkg_hash_ext,[ - {<<"getopt">>, <<"53E1AB83B9CEB65C9672D3E7A35B8092E9BDC9B3EE80721471A161C10C59959C">>}, - {<<"gpb">>, <<"B355A5982B604D6C044EBB6013E5FE65D30C30D0700D35317E7066691EB6BD61">>}, - {<<"providers">>, <<"E45745ADE9C476A9A469EA0840E418AB19360DC44F01A233304E118A44486BA0">>}]} + {<<"gpb">>, <<"EA3A81F83524D5685395594B57BB515F4631A54D27514219D67024BD251C9E82">>}]} ]. diff --git a/src/grpcbox_plugin.app.src b/src/grpcbox_plugin.app.src index 072d3ca..2ed0a55 100644 --- a/src/grpcbox_plugin.app.src +++ b/src/grpcbox_plugin.app.src @@ -2,7 +2,7 @@ [{description,"Rebar3 plugin to generate behaviours for grpc services"}, {vsn,"git"}, {registered,[]}, - {applications,[kernel,stdlib,gpb,providers]}, + {applications,[kernel,stdlib,providers,gpb]}, {env,[]}, {modules,[]}, {licenses,["Apache 2.0"]}, diff --git a/src/grpcbox_plugin_prv.erl b/src/grpcbox_plugin_prv.erl index 4fe9418..d3367fe 100644 --- a/src/grpcbox_plugin_prv.erl +++ b/src/grpcbox_plugin_prv.erl @@ -1,12 +1,12 @@ -module(grpcbox_plugin_prv). +-behaviour(provider). -export([init/1, do/1, format_error/1]). --include_lib("providers/include/providers.hrl"). - -define(PROVIDER, gen). -define(NAMESPACE, grpc). -define(DEPS, [{default, app_discovery}]). +-define(record_to_tuplelist(RecName, Rec), lists:zip(record_info(fields, RecName),tl(tuple_to_list(Rec)))). %% =================================================================== %% Public API @@ -54,26 +54,42 @@ format_error(Reason) -> handle_app(AppInfo, Options, State) -> Opts = rebar_app_info:opts(AppInfo), - BeamOutDir = rebar_app_info:ebin_dir(AppInfo), GrpcOpts = rebar_opts:get(Opts, grpc, []), GpbOpts = proplists:get_value(gpb_opts, GrpcOpts, []), BaseDir = rebar_app_info:dir(AppInfo), + GrpcCreateServices = proplists:get_value(create_services, GrpcOpts, true), GrpcOptOutDir = proplists:get_value(out_dir, GrpcOpts, filename:join(BaseDir, "src")), + BeamOutDir = proplists:get_value(beam_out_dir, GrpcOpts, rebar_app_info:ebin_dir(AppInfo)), + GrpcKeepBeams = proplists:get_value(keep_beams, GrpcOpts, false), GrpcOutDir = filename:join(BaseDir, GrpcOptOutDir), GpbOutDir = filename:join(BaseDir, proplists:get_value(o, GpbOpts, GrpcOptOutDir)), - ProtosDirs = case proplists:get_all_values(protos, Options) of - [] -> - case proplists:get_value(protos, GrpcOpts, [filename:join("priv", "protos")]) of - [H | _] = Ds when is_list(H) -> - Ds; - D -> - [D] - end; - Ds -> - Ds - end, - ProtoFiles = lists:append([filelib:wildcard(filename:join([BaseDir, D, "*.proto"])) || D <- ProtosDirs]), + ProtoFiles = case proplists:get_all_values(proto_files, Options) of + [] -> + case proplists:get_value(proto_files, GrpcOpts) of + undefined -> + ProtosDirs = case proplists:get_all_values(protos, Options) of + [] -> + case proplists:get_value(protos, GrpcOpts, [filename:join("priv", "protos")]) of + [H | _] = Ds when is_list(H) -> + Ds; + D -> + [D] + end; + Ds -> + Ds + end, + + lists:append([filelib:wildcard(filename:join([BaseDir, D, "*.proto"])) || D <- ProtosDirs]); + [H | _] = Ds when is_list(H) -> + Ds; + D -> + [D] + end; + Ds -> + Ds + end, + ProtoFilesAbs = lists:append([filelib:wildcard(filename:join([BaseDir, D])) || D <- ProtoFiles]), Type = case proplists:get_value(type, Options, undefined) of undefined -> @@ -82,10 +98,19 @@ handle_app(AppInfo, Options, State) -> T end, Templates = templates(Type), - ProtoModules = [compile_pb(Filename, GpbOutDir, BeamOutDir, GpbOpts) || Filename <- ProtoFiles], - [gen_services(Templates, ProtoModule, ProtoBeam, GrpcOutDir, GrpcOpts, State) - || {ProtoModule, ProtoBeam} <- ProtoModules], - ok. + ProtoModules = [compile_pb(Filename, GpbOutDir, BeamOutDir, GpbOpts) || Filename <- ProtoFilesAbs], + case GrpcCreateServices of + true -> + [gen_services(Templates, ProtoModule, ProtoBeam, GrpcOutDir, GrpcOpts, State) + || {ProtoModule, ProtoBeam} <- ProtoModules], + ok; + _ -> + ok + end, + case GrpcKeepBeams of + true -> ok; + false -> [file:delete(ProtoBeam) || {_ProtoModule, ProtoBeam} <- ProtoModules] + end. compile_pb(Filename, OutDir, BeamOutDir, GpbOpts) -> ModuleName = lists:flatten( @@ -98,16 +123,20 @@ compile_pb(Filename, OutDir, BeamOutDir, GpbOpts) -> case needs_update(Filename, GeneratedPB) of true -> rebar_log:log(info, "Writing ~s", [GeneratedPB]), - case gpb_compile:file(Filename, [{rename,{msg_name,snake_case}}, - {rename,{msg_fqname,base_name}}, - use_packages, maps, - strings_as_binaries, {i, "."}, + %% unless the calling app overrides, we will default defs_as_proplists to true + %% resulting in service defs using proplists + %% Overriding the default with a value of false will result in the service defs using maps + GpbDefsAsProplists = proplists:get_value(defs_as_proplists, GpbOpts, true), + case gpb_compile:file(Filename, [{rename,{msg_fqname,base_name}}, + use_packages, + {defs_as_proplists, GpbDefsAsProplists}, + {i, "."}, {report_errors, false}, {o, OutDir} | GpbOpts]) of ok -> ok; {error, Error} -> - erlang:error(?PRV_ERROR({gpb, Filename, Error})) + throw({error, format_error(Error)}) end; false -> ok @@ -123,7 +152,7 @@ compile_pb(Filename, OutDir, BeamOutDir, GpbOpts) -> ok; {error, Errors, Warnings} -> log_warnings(Warnings), - throw(?PRV_ERROR({compile_errors, Errors})) + throw({error, format_error(Errors)}) end; false -> ok @@ -141,6 +170,7 @@ gen_services(Templates, ProtoModule, ProtoBeam, OutDir, GrpcConfig, State) -> [rebar_templater:new(TemplateName, maps:to_list(Service), true, State) || {Service, _, TemplateName} <- Services]. + gen_service_def(Service, ProtoModule, GrpcConfig, FullOutDir) -> ServiceModules = proplists:get_value(service_modules, GrpcConfig, []), ServicePrefix = proplists:get_value(prefix, GrpcConfig, ""), @@ -154,8 +184,12 @@ gen_service_def(Service, ProtoModule, GrpcConfig, FullOutDir) -> methods => [resolve_method(M, ProtoModule) || M <- Methods]}. resolve_method(Method, ProtoModule) -> - MessageType = {message_type, ProtoModule:msg_name_to_fqbin(maps:get(input, Method))}, - MethodData = lists:flatmap(fun normalize_method_opt/1, maps:to_list(Method)), + %% if the gpb option defs_as_proplists is set to false, then service defs will be maps + %% so just force the methods to maps type here + rebar_log:log(info, "METHOD: ~p", [Method]), + MethodMap = ensure_map(Method), + MessageType = {message_type, ProtoModule:msg_name_to_fqbin(maps:get(input, MethodMap))}, + MethodData = lists:flatmap(fun normalize_method_opt/1, maps:to_list(MethodMap)), [MessageType | MethodData]. filter_outdated({#{module_name := ModuleName}, TemplateSuffix, _}, OutDir, ProtoBeam) -> @@ -209,3 +243,8 @@ log_warnings(Warnings) -> rebar_api:warn("Warning building ~s~n", [File]), [rebar_api:warn(" ~p: ~s", [Line, M:format_error(E)]) || {Line, M, E} <- Es] end || {File, Es} <- Warnings]. + +ensure_map(S) when is_map(S)-> + S; +ensure_map(S) when is_list(S)-> + maps:from_list(S). \ No newline at end of file