From 5456bb85019a64fa89bdf036183407e2a7f478bd Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Wed, 9 Feb 2022 20:38:49 -0300 Subject: [PATCH 01/19] Create Middleware to communicate with user function --- .../grpc/protocol/action/stream_handler.ex | 3 + .../lib/massa_proxy/runtime/middleware.ex | 64 +++++++++++++++++++ .../runtime/middleware_supervisor.ex | 6 ++ 3 files changed, 73 insertions(+) create mode 100644 apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex create mode 100644 apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex index 390a158..95711ff 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex @@ -15,6 +15,9 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler do client_stream = ActionClient.handle_streamed(conn), :ok <- client_stream |> run_stream(messages) |> Stream.run(), {:ok, consumer_stream} <- GRPC.Stub.recv(client_stream) do + # inside of a middleware do anything else before send reply + # consumer_stream = Stream.map(consumer_stream, fn elem -> map(elem) end) + consumer_stream |> Stream.each(fn {:ok, r} -> GRPC.Server.send_reply(stream, ActionProtocol.decode(ctx, r)) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex new file mode 100644 index 0000000..bea7056 --- /dev/null +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -0,0 +1,64 @@ +defmodule MassaProxy.Runtime.Middleware do + @moduledoc """ + Middleware is a module that can be used to add functionality + to interact with the user role and other remote middlewares. + """ + use GenServer + require Logger + + alias Cloudstate.Action.ActionResponse + alias Cloudstate.Action.ActionProtocol.Stub, as: ActionClient + + import MassaProxy.Util, only: [get_connection: 0] + + def init(state) do + {:ok, state} + end + + @impl true + def handle_call( + {:handle_unary, message}, + _from, + %{command_processor: command_processor} = state + ) do + result = + with {:ok, channel} <- get_connection(), + {:ok, result} <- ActionClient.handle_unary(channel, message), + {:ok, %ActionResponse{response: _response, side_effects: effects} = result} <- + process_command(command_processor, result) do + handle_effects(effects) + {:ok, result} + else + {:error, reason} -> {:error, "Failure to make unary request #{inspect(reason)}"} + end + + Logger.debug("User function response #{inspect(result)}") + + {:reply, result, state} + end + + @impl true + def handle_call({:handle_streamed, _messages}, from, state) do + spawn(fn -> + stream_result = nil + GenServer.reply(from, stream_result) + end) + + {:noreply, state} + end + + def unary_req(server, message) do + GenServer.call(server, {:handle_unary, message}) + end + + def stream_req(server, messages) do + GenServer.call(server, {:handle_streamed, messages}) + end + + defp handle_effects(_effects) do + end + + defp process_command(_command_processor, action_response) do + {:ok, action_response} + end +end diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex new file mode 100644 index 0000000..e965310 --- /dev/null +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex @@ -0,0 +1,6 @@ +defmodule MassaProxy.Runtime.MiddlewareSupervisor do + @moduledoc """ + + """ + use DynamicSupervisor +end From 64488fd90a3d9307c1985f62e414eed9bd631f9d Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Wed, 9 Feb 2022 23:23:39 -0300 Subject: [PATCH 02/19] Add some functions --- .../lib/massa_proxy/runtime/middleware.ex | 33 +++++++++++++++---- .../runtime/middleware_supervisor.ex | 20 +++++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex index bea7056..4f2537b 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -23,9 +23,9 @@ defmodule MassaProxy.Runtime.Middleware do ) do result = with {:ok, channel} <- get_connection(), - {:ok, result} <- ActionClient.handle_unary(channel, message), - {:ok, %ActionResponse{response: _response, side_effects: effects} = result} <- - process_command(command_processor, result) do + {:ok, %ActionResponse{side_effects: effects} = commands} <- + ActionClient.handle_unary(channel, message), + {:ok, result} <- process_command(command_processor, commands) do handle_effects(effects) {:ok, result} else @@ -55,10 +55,31 @@ defmodule MassaProxy.Runtime.Middleware do GenServer.call(server, {:handle_streamed, messages}) end - defp handle_effects(_effects) do + defp process_command( + _command_processor, + %ActionResponse{response: {:reply, %Cloudstate.Reply{} = _reply}} = message + ) do + {:ok, message} end - defp process_command(_command_processor, action_response) do - {:ok, action_response} + defp process_command( + _command_processor, + %ActionResponse{response: {:failure, %Cloudstate.Failure{} = _failure}} = message + ) do + {:ok, message} end + + defp process_command( + _command_processor, + %ActionResponse{response: {:forward, %Cloudstate.Forward{} = _forward}} = message + ) do + {:ok, message} + end + + defp handle_effects([]), do: {:ok, []} + + defp handle_effects(effects) when is_list(effects) and length(effects) > 0 do + end + + defp handle_effects(_), do: {:ok, []} end diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex index e965310..e260548 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex @@ -3,4 +3,24 @@ defmodule MassaProxy.Runtime.MiddlewareSupervisor do """ use DynamicSupervisor + + @impl true + def init(_opts), do: DynamicSupervisor.init(strategy: :one_for_one) + + @doc false + def start_link(_opts), + do: DynamicSupervisor.start_link(__MODULE__, [shutdown: 120_000], name: __MODULE__) + + def start_middleware(state) do + child_spec = %{ + id: MassaProxy.Runtime.Middleware, + start: {MassaProxy.Runtime.Middleware, :start_link, [state]}, + restart: :transient + } + + case DynamicSupervisor.start_child(__MODULE__, child_spec) do + {:error, {:already_started, pid}} -> {:ok, pid} + {:ok, pid} -> {:ok, pid} + end + end end From eae264730874657988caf98e7bd5a08f33ddac4f Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Thu, 10 Feb 2022 22:18:57 -0300 Subject: [PATCH 03/19] Use Middleware to handle user function commands --- .../lib/massa_proxy/runtime/grpc/dispatcher.ex | 13 +++++++++---- .../grpc/protocol/action/unary_handler.ex | 14 +++++--------- .../lib/massa_proxy/runtime/middleware.ex | 11 +++++++---- .../massa_proxy/runtime/middleware_supervisor.ex | 16 ++++++++++++---- apps/massa_proxy/lib/supervisor.ex | 2 ++ 5 files changed, 35 insertions(+), 21 deletions(-) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/dispatcher.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/dispatcher.ex index 59d6f2d..0616e76 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/dispatcher.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/dispatcher.ex @@ -5,6 +5,7 @@ defmodule MassaProxy.Runtime.Grpc.Server.Dispatcher do require Logger alias MassaProxy.Runtime.Grpc.Protocol.Action.Handler, as: ActionHandler alias MassaProxy.Runtime.Grpc.Protocol.EventSourced.Handler, as: EventSourcedHandler + alias MassaProxy.Runtime.MiddlewareSupervisor def dispatch( %{ @@ -22,10 +23,14 @@ defmodule MassaProxy.Runtime.Grpc.Server.Dispatcher do "Handle stream: #{inspect(stream)}. With persistence id: #{inspect(persistence_id)}" ) - case entity_type do - "cloudstate.action.ActionProtocol" -> ActionHandler.handle(payload) - "cloudstate.eventsourced.EventSourced" -> EventSourcedHandler.handle(payload) - _ -> Logger.error("Not Implemented Entity type #{entity_type}") + with {:ok, _pid} <- MiddlewareSupervisor.start_middleware(payload) do + case entity_type do + "cloudstate.action.ActionProtocol" -> ActionHandler.handle(payload) + "cloudstate.eventsourced.EventSourced" -> EventSourcedHandler.handle(payload) + _ -> Logger.error("Not Implemented Entity type #{entity_type}") + end + else + error -> Logger.error("Middleware error #{inspect(error)}") end end end diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex index 9d64436..d570819 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex @@ -3,22 +3,18 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Unary.Handler do This module is responsible for handling unary requests of the Action protocol """ require Logger - alias Cloudstate.Action.ActionProtocol.Stub, as: ActionClient alias MassaProxy.Runtime.Grpc.Protocol.Action.Protocol, as: ActionProtocol + alias MassaProxy.Runtime.Middleware - import MassaProxy.Util, only: [get_connection: 0] - - def handle_unary(ctx) do - # Call user function and return - message = ActionProtocol.build_msg(ctx) - + def handle_unary(%{entity_type: entity_type} = ctx) do response = - with {:ok, channel} <- get_connection(), - {:ok, response} <- ActionClient.handle_unary(channel, message) do + with message <- ActionProtocol.build_msg(ctx), + {:ok, response} <- Middleware.unary_req(entity_type, message) do ActionProtocol.decode(ctx, response) else {:error, reason} -> {:error, "Failure to make unary request #{inspect(reason)}"} end + Logger.debug(fn -> "User function response #{inspect(response)}" end) response diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex index 4f2537b..a48e0b1 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -47,12 +47,12 @@ defmodule MassaProxy.Runtime.Middleware do {:noreply, state} end - def unary_req(server, message) do - GenServer.call(server, {:handle_unary, message}) + def unary_req(entity_type, message) do + GenServer.call(get_name(entity_type), {:handle_unary, message}) end - def stream_req(server, messages) do - GenServer.call(server, {:handle_streamed, messages}) + def stream_req(entity_type, messages) do + GenServer.call(get_name(entity_type), {:handle_streamed, messages}) end defp process_command( @@ -82,4 +82,7 @@ defmodule MassaProxy.Runtime.Middleware do end defp handle_effects(_), do: {:ok, []} + + defp get_name(entity_type), + do: entity_type |> String.split(".") |> Enum.at(-1) end diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex index e260548..36e592c 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex @@ -1,9 +1,11 @@ defmodule MassaProxy.Runtime.MiddlewareSupervisor do @moduledoc """ - + Supervisor for the middleware stack. """ use DynamicSupervisor + alias MassaProxy.Runtime.Middleware + @impl true def init(_opts), do: DynamicSupervisor.init(strategy: :one_for_one) @@ -11,10 +13,13 @@ defmodule MassaProxy.Runtime.MiddlewareSupervisor do def start_link(_opts), do: DynamicSupervisor.start_link(__MODULE__, [shutdown: 120_000], name: __MODULE__) - def start_middleware(state) do + def start_middleware(%{entity_type: entity_type} = state) do + mod = get_name(entity_type) + process_name = Module.concat(Middleware, mod) + child_spec = %{ - id: MassaProxy.Runtime.Middleware, - start: {MassaProxy.Runtime.Middleware, :start_link, [state]}, + id: process_name, + start: {Middleware, :start_link, [%{state | name: process_name}]}, restart: :transient } @@ -23,4 +28,7 @@ defmodule MassaProxy.Runtime.MiddlewareSupervisor do {:ok, pid} -> {:ok, pid} end end + + defp get_name(entity_type), + do: entity_type |> String.split(".") |> Enum.at(-1) end diff --git a/apps/massa_proxy/lib/supervisor.ex b/apps/massa_proxy/lib/supervisor.ex index 081a5e0..ac59ba6 100644 --- a/apps/massa_proxy/lib/supervisor.ex +++ b/apps/massa_proxy/lib/supervisor.ex @@ -15,6 +15,8 @@ defmodule MassaProxy.Children do {Task.Supervisor, name: MassaProxy.TaskSupervisor}, {Registry, [name: MassaProxy.LocalRegistry, keys: :unique]}, {DynamicSupervisor, [name: MassaProxy.LocalSupervisor, strategy: :one_for_one]}, + {DynamicSupervisor, + [name: MassaProxy.Runtime.MiddlewareSupervisor, strategy: :one_for_one]}, {MassaProxy.Infra.Cache.Distributed, []}, local_node(), {MassaProxy.Entity.EntityRegistry.Supervisor, [%{}]}, From 7c1716e6ee48e61aea0afa1e69e8b59f836c2241 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Fri, 11 Feb 2022 21:37:08 -0300 Subject: [PATCH 04/19] Some adjusts --- .../lib/massa_proxy/runtime/middleware.ex | 33 ++++++++++++++++--- .../runtime/middleware_supervisor.ex | 15 ++++++--- apps/massa_proxy/lib/massa_proxy/util.ex | 6 +++- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex index a48e0b1..7552fb6 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -11,21 +11,27 @@ defmodule MassaProxy.Runtime.Middleware do import MassaProxy.Util, only: [get_connection: 0] + @impl true def init(state) do {:ok, state} end + def start_link(%{name: name} = state) do + GenServer.start_link(__MODULE__, state, name: name) + end + @impl true def handle_call( {:handle_unary, message}, _from, - %{command_processor: command_processor} = state + # %{command_processor: command_processor} = state + state ) do result = with {:ok, channel} <- get_connection(), {:ok, %ActionResponse{side_effects: effects} = commands} <- ActionClient.handle_unary(channel, message), - {:ok, result} <- process_command(command_processor, commands) do + {:ok, result} <- process_command(nil, commands) do handle_effects(effects) {:ok, result} else @@ -47,11 +53,18 @@ defmodule MassaProxy.Runtime.Middleware do {:noreply, state} end + @impl true + def handle_info(msg, state) do + Logger.notice("Received unexpected message: #{inspect(msg)}") + + {:noreply, state} + end + def unary_req(entity_type, message) do GenServer.call(get_name(entity_type), {:handle_unary, message}) end - def stream_req(entity_type, messages) do + def streamed_req(entity_type, messages) do GenServer.call(get_name(entity_type), {:handle_streamed, messages}) end @@ -76,6 +89,10 @@ defmodule MassaProxy.Runtime.Middleware do {:ok, message} end + defp process_command(nil, message) do + {:ok, message} + end + defp handle_effects([]), do: {:ok, []} defp handle_effects(effects) when is_list(effects) and length(effects) > 0 do @@ -83,6 +100,12 @@ defmodule MassaProxy.Runtime.Middleware do defp handle_effects(_), do: {:ok, []} - defp get_name(entity_type), - do: entity_type |> String.split(".") |> Enum.at(-1) + defp get_name(entity_type) do + mod = + entity_type + |> String.split(".") + |> Enum.at(-1) + + Module.concat(__MODULE__, mod) + end end diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex index 36e592c..03e0082 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware_supervisor.ex @@ -14,12 +14,11 @@ defmodule MassaProxy.Runtime.MiddlewareSupervisor do do: DynamicSupervisor.start_link(__MODULE__, [shutdown: 120_000], name: __MODULE__) def start_middleware(%{entity_type: entity_type} = state) do - mod = get_name(entity_type) - process_name = Module.concat(Middleware, mod) + process_name = get_name(entity_type) child_spec = %{ id: process_name, - start: {Middleware, :start_link, [%{state | name: process_name}]}, + start: {Middleware, :start_link, [Map.put(state, :name, process_name)]}, restart: :transient } @@ -29,6 +28,12 @@ defmodule MassaProxy.Runtime.MiddlewareSupervisor do end end - defp get_name(entity_type), - do: entity_type |> String.split(".") |> Enum.at(-1) + defp get_name(entity_type) do + mod = + entity_type + |> String.split(".") + |> Enum.at(-1) + + Module.concat(Middleware, mod) + end end diff --git a/apps/massa_proxy/lib/massa_proxy/util.ex b/apps/massa_proxy/lib/massa_proxy/util.ex index e71b658..6a13bf9 100644 --- a/apps/massa_proxy/lib/massa_proxy/util.ex +++ b/apps/massa_proxy/lib/massa_proxy/util.ex @@ -155,7 +155,11 @@ defmodule MassaProxy.Util do def get_module(filename, bindings \\ []), do: EEx.eval_file(filename, bindings) def get_connection(), - do: GRPC.Stub.connect(get_address(is_uds_enable?()), interceptors: [GRPC.Logger.Client]) + do: + GRPC.Stub.connect(get_address(is_uds_enable?()), + interceptors: [GRPC.Logger.Client], + adapter_opts: %{http2_opts: %{keepalive: 10000}} + ) def get_uds_address(), do: Application.get_env(:massa_proxy, :user_function_sock_addr, "/var/run/cloudstate.sock") From e5e8630917420f1a01ad22a871676c4ceb306c1b Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Sat, 12 Feb 2022 12:46:25 -0300 Subject: [PATCH 05/19] Add streamed on middleware --- .../grpc/protocol/action/stream_handler.ex | 14 ++----- .../lib/massa_proxy/runtime/middleware.ex | 38 ++++++++++++++++++- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex index 95711ff..e63847f 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex @@ -5,19 +5,13 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler do alias Cloudstate.Action.ActionProtocol.Stub, as: ActionClient alias MassaProxy.Runtime.Grpc.Protocol.Action.Protocol, as: ActionProtocol + alias MassaProxy.Runtime.Middleware import MassaProxy.Util, only: [get_connection: 0] - def handle_streamed(%{stream: stream} = ctx) do - messages = ActionProtocol.build_stream(ctx) - - with {:ok, conn} <- get_connection(), - client_stream = ActionClient.handle_streamed(conn), - :ok <- client_stream |> run_stream(messages) |> Stream.run(), - {:ok, consumer_stream} <- GRPC.Stub.recv(client_stream) do - # inside of a middleware do anything else before send reply - # consumer_stream = Stream.map(consumer_stream, fn elem -> map(elem) end) - + def handle_streamed(%{entity_type: entity_type, stream: stream} = ctx) do + with messages <- ActionProtocol.build_stream(ctx), + {:ok, consumer_stream} <- Middleware.streamed_req(entity_type, messages) do consumer_stream |> Stream.each(fn {:ok, r} -> GRPC.Server.send_reply(stream, ActionProtocol.decode(ctx, r)) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex index 7552fb6..bd68ddf 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -44,9 +44,31 @@ defmodule MassaProxy.Runtime.Middleware do end @impl true - def handle_call({:handle_streamed, _messages}, from, state) do + def handle_call({:handle_streamed, messages}, from, state) do spawn(fn -> - stream_result = nil + stream_result = + with {:ok, conn} <- get_connection(), + client_stream = ActionClient.handle_streamed(conn), + :ok <- client_stream |> run_stream(messages) |> Stream.run(), + {:ok, %ActionResponse{side_effects: effects} = commands} <- + GRPC.Stub.recv(client_stream) do + consumer_stream = + Stream.map(commands, fn it -> + case process_command(nil, it) do + {:ok, result} -> + {:ok, result} + + {:error, reason} -> + {:error, "Failure on process client stream #{inspect(reason)}"} + end + end) + + handle_effects(effects) + {:ok, consumer_stream} + else + {:error, reason} -> {:error, reason} + end + GenServer.reply(from, stream_result) end) @@ -108,4 +130,16 @@ defmodule MassaProxy.Runtime.Middleware do Module.concat(__MODULE__, mod) end + + defp run_stream(client_stream, messages) do + Stream.map(messages, &send_stream_msg(client_stream, &1)) + end + + defp send_stream_msg(client_stream, :halt) do + GRPC.Stub.end_stream(client_stream) + end + + defp send_stream_msg(client_stream, msg) do + GRPC.Stub.send_request(client_stream, msg, []) + end end From 4ea508136b1733d52ab4946433a7d6a23d6fc0b0 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Sat, 12 Feb 2022 22:55:27 -0300 Subject: [PATCH 06/19] Add debug messages --- .../grpc/protocol/action/stream_handler.ex | 9 ++-- .../grpc/protocol/action/unary_handler.ex | 4 +- .../lib/massa_proxy/runtime/middleware.ex | 44 ++++++++++++++----- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex index e63847f..0e09f73 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex @@ -2,6 +2,7 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler do @moduledoc """ This module is responsible for handling stream requests of the Action protocol """ + require Logger alias Cloudstate.Action.ActionProtocol.Stub, as: ActionClient alias MassaProxy.Runtime.Grpc.Protocol.Action.Protocol, as: ActionProtocol @@ -9,16 +10,18 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler do import MassaProxy.Util, only: [get_connection: 0] - def handle_streamed(%{entity_type: entity_type, stream: stream} = ctx) do + def handle_streamed(%{stream: stream} = ctx) do with messages <- ActionProtocol.build_stream(ctx), - {:ok, consumer_stream} <- Middleware.streamed_req(entity_type, messages) do + {:ok, consumer_stream} <- Middleware.streamed_req(ctx, messages) do consumer_stream |> Stream.each(fn {:ok, r} -> GRPC.Server.send_reply(stream, ActionProtocol.decode(ctx, r)) end) |> Stream.run() else - {:error, _reason} = err -> err + {:error, _reason} = err -> + Logger.error("Error while handling stream request: #{inspect(err)}") + err end end diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex index d570819..19e51f5 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex @@ -6,10 +6,10 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Unary.Handler do alias MassaProxy.Runtime.Grpc.Protocol.Action.Protocol, as: ActionProtocol alias MassaProxy.Runtime.Middleware - def handle_unary(%{entity_type: entity_type} = ctx) do + def handle_unary(ctx) do response = with message <- ActionProtocol.build_msg(ctx), - {:ok, response} <- Middleware.unary_req(entity_type, message) do + {:ok, response} <- Middleware.unary_req(ctx, message) do ActionProtocol.decode(ctx, response) else {:error, reason} -> {:error, "Failure to make unary request #{inspect(reason)}"} diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex index bd68ddf..48ba252 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -22,7 +22,7 @@ defmodule MassaProxy.Runtime.Middleware do @impl true def handle_call( - {:handle_unary, message}, + {:handle_unary, %{context: context, payload: message} = _input}, _from, # %{command_processor: command_processor} = state state @@ -31,7 +31,7 @@ defmodule MassaProxy.Runtime.Middleware do with {:ok, channel} <- get_connection(), {:ok, %ActionResponse{side_effects: effects} = commands} <- ActionClient.handle_unary(channel, message), - {:ok, result} <- process_command(nil, commands) do + {:ok, result} <- process_command(nil, context, commands) do handle_effects(effects) {:ok, result} else @@ -44,17 +44,27 @@ defmodule MassaProxy.Runtime.Middleware do end @impl true - def handle_call({:handle_streamed, messages}, from, state) do + def handle_call( + {:handle_streamed, %{context: context, payload: messages} = _input}, + from, + state + ) do spawn(fn -> stream_result = with {:ok, conn} <- get_connection(), client_stream = ActionClient.handle_streamed(conn), :ok <- client_stream |> run_stream(messages) |> Stream.run(), - {:ok, %ActionResponse{side_effects: effects} = commands} <- + {:ok, commands} <- GRPC.Stub.recv(client_stream) do + Logger.debug("Commands: #{inspect(commands)} Client Stream: #{inspect(client_stream)}") + {:ok, commands} + consumer_stream = Stream.map(commands, fn it -> - case process_command(nil, it) do + Logger.debug("Yeah: #{inspect(it)}") + {:ok, it} + + case process_command(nil, context, it) do {:ok, result} -> {:ok, result} @@ -63,10 +73,14 @@ defmodule MassaProxy.Runtime.Middleware do end end) - handle_effects(effects) + # handle_effects(effects) {:ok, consumer_stream} else - {:error, reason} -> {:error, reason} + {:ok, []} -> + {:error, "Client not returned a stream"} + + {:error, reason} -> + {:error, reason} end GenServer.reply(from, stream_result) @@ -82,16 +96,17 @@ defmodule MassaProxy.Runtime.Middleware do {:noreply, state} end - def unary_req(entity_type, message) do - GenServer.call(get_name(entity_type), {:handle_unary, message}) + def unary_req(%{entity_type: entity_type} = ctx, message) do + GenServer.call(get_name(entity_type), {:handle_unary, %{context: ctx, payload: message}}) end - def streamed_req(entity_type, messages) do - GenServer.call(get_name(entity_type), {:handle_streamed, messages}) + def streamed_req(%{entity_type: entity_type} = ctx, messages) do + GenServer.call(get_name(entity_type), {:handle_streamed, %{context: ctx, payload: messages}}) end defp process_command( _command_processor, + _context, %ActionResponse{response: {:reply, %Cloudstate.Reply{} = _reply}} = message ) do {:ok, message} @@ -99,6 +114,7 @@ defmodule MassaProxy.Runtime.Middleware do defp process_command( _command_processor, + _context, %ActionResponse{response: {:failure, %Cloudstate.Failure{} = _failure}} = message ) do {:ok, message} @@ -106,12 +122,13 @@ defmodule MassaProxy.Runtime.Middleware do defp process_command( _command_processor, + _context, %ActionResponse{response: {:forward, %Cloudstate.Forward{} = _forward}} = message ) do {:ok, message} end - defp process_command(nil, message) do + defp process_command(nil, _context, message) do {:ok, message} end @@ -132,14 +149,17 @@ defmodule MassaProxy.Runtime.Middleware do end defp run_stream(client_stream, messages) do + Logger.debug("Running client stream #{inspect(messages)}") Stream.map(messages, &send_stream_msg(client_stream, &1)) end defp send_stream_msg(client_stream, :halt) do + Logger.debug("send_stream_msg :halt") GRPC.Stub.end_stream(client_stream) end defp send_stream_msg(client_stream, msg) do + Logger.debug("send_stream_msg #{inspect(msg)}") GRPC.Stub.send_request(client_stream, msg, []) end end From 4ab80003beec29f315485a412d8c12175db826bb Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Sun, 13 Feb 2022 06:37:04 -0300 Subject: [PATCH 07/19] Nothing --- apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex index 48ba252..4a4bcd8 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -60,9 +60,8 @@ defmodule MassaProxy.Runtime.Middleware do {:ok, commands} consumer_stream = - Stream.map(commands, fn it -> + Stream.map(commands, fn {:ok, it} -> Logger.debug("Yeah: #{inspect(it)}") - {:ok, it} case process_command(nil, context, it) do {:ok, result} -> From 48c828c884ac9019953b7d955a997226fb1c55a6 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Sun, 13 Feb 2022 17:59:44 -0300 Subject: [PATCH 08/19] Added some validations --- .../grpc/protocol/action/stream_handler.ex | 9 ++- .../lib/massa_proxy/runtime/middleware.ex | 56 ++++++++++++++----- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex index 0e09f73..01cbcd7 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex @@ -14,8 +14,13 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler do with messages <- ActionProtocol.build_stream(ctx), {:ok, consumer_stream} <- Middleware.streamed_req(ctx, messages) do consumer_stream - |> Stream.each(fn {:ok, r} -> - GRPC.Server.send_reply(stream, ActionProtocol.decode(ctx, r)) + |> Stream.each(fn + {:ok, r} -> + GRPC.Server.send_reply(stream, ActionProtocol.decode(ctx, r)) + + {:error, _reason} = err -> + Logger.error("Error while handling stream request: #{inspect(err)}") + err end) |> Stream.run() else diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex index 4a4bcd8..79f77cb 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -50,29 +50,49 @@ defmodule MassaProxy.Runtime.Middleware do state ) do spawn(fn -> + # messages = ActionProtocol.build_stream(ctx) + # with {:ok, conn} <- get_connection(), + # client_stream = ActionClient.handle_streamed(conn), + # :ok <- client_stream |> run_stream(messages) |> Stream.run(), + # {:ok, consumer_stream} <- GRPC.Stub.recv(client_stream) do + # consumer_stream + # |> Stream.each(fn {:ok, r} -> + # GRPC.Server.send_reply(stream, ActionProtocol.decode(ctx, r)) + # end) + # |> Stream.run() + # else + # {:error, _reason} = err -> err + # end + stream_result = with {:ok, conn} <- get_connection(), client_stream = ActionClient.handle_streamed(conn), - :ok <- client_stream |> run_stream(messages) |> Stream.run(), - {:ok, commands} <- - GRPC.Stub.recv(client_stream) do - Logger.debug("Commands: #{inspect(commands)} Client Stream: #{inspect(client_stream)}") - {:ok, commands} + :ok <- run_stream(client_stream, messages) |> Stream.run(), + {:ok, consumer_stream} <- GRPC.Stub.recv(client_stream) do + Logger.debug( + "Commands: #{inspect(consumer_stream)} Client Stream: #{inspect(client_stream)}" + ) consumer_stream = - Stream.map(commands, fn {:ok, it} -> - Logger.debug("Yeah: #{inspect(it)}") + consumer_stream + |> Stream.map(fn + {:ok, %ActionResponse{side_effects: effects} = command} -> + Logger.debug("Consumer Stream result: #{inspect(command)}") + + case process_command(nil, context, command) do + {:ok, result} -> + {:ok, result} + + {:error, reason} -> + {:error, "Failure on process client stream #{inspect(reason)}"} + end - case process_command(nil, context, it) do - {:ok, result} -> - {:ok, result} + handle_effects(effects) - {:error, reason} -> - {:error, "Failure on process client stream #{inspect(reason)}"} - end + {:error, reason} -> + {:error, "Failure on process client stream #{inspect(reason)}"} end) - # handle_effects(effects) {:ok, consumer_stream} else {:ok, []} -> @@ -149,9 +169,15 @@ defmodule MassaProxy.Runtime.Middleware do defp run_stream(client_stream, messages) do Logger.debug("Running client stream #{inspect(messages)}") - Stream.map(messages, &send_stream_msg(client_stream, &1)) + + Stream.filter(messages, &is_command_valid?(&1)) + |> Stream.map(&send_stream_msg(client_stream, &1)) end + defp is_command_valid?(:halt), do: true + defp is_command_valid?(%Cloudstate.Action.ActionCommand{payload: nil}), do: false + defp is_command_valid?(%Cloudstate.Action.ActionCommand{payload: _payload}), do: true + defp send_stream_msg(client_stream, :halt) do Logger.debug("send_stream_msg :halt") GRPC.Stub.end_stream(client_stream) From 6fbccbdf0fc81ff676ecd610c7687dd69b6b1d72 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Sun, 13 Feb 2022 19:31:24 -0300 Subject: [PATCH 09/19] Add streamed middleware partial support --- .../runtime/grpc/protocol/action/protocol.ex | 9 ++++-- .../grpc/protocol/action/stream_handler.ex | 1 + .../lib/massa_proxy/runtime/middleware.ex | 29 ++++++------------- apps/massa_proxy/lib/massa_proxy/util.ex | 4 +-- 4 files changed, 19 insertions(+), 24 deletions(-) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex index cb7433c..86a8425 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex @@ -28,8 +28,13 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Protocol do ) end - def build_msg(ctx, :payload) do - ActionCommand.new(payload: build_payload(ctx)) + def build_msg(%{service_name: service_name, original_method: original_method} = ctx, :payload) do + ActionCommand.new( + service_name: service_name, + name: original_method, + metadata: Metadata.new(), + payload: build_payload(ctx) + ) end @spec build_stream(t()) :: Enumerable.t() diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex index 01cbcd7..9f86a50 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex @@ -16,6 +16,7 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler do consumer_stream |> Stream.each(fn {:ok, r} -> + Logger.info("Decode -----> #{inspect(r)}") GRPC.Server.send_reply(stream, ActionProtocol.decode(ctx, r)) {:error, _reason} = err -> diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex index 79f77cb..c1da0c6 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -50,20 +50,6 @@ defmodule MassaProxy.Runtime.Middleware do state ) do spawn(fn -> - # messages = ActionProtocol.build_stream(ctx) - # with {:ok, conn} <- get_connection(), - # client_stream = ActionClient.handle_streamed(conn), - # :ok <- client_stream |> run_stream(messages) |> Stream.run(), - # {:ok, consumer_stream} <- GRPC.Stub.recv(client_stream) do - # consumer_stream - # |> Stream.each(fn {:ok, r} -> - # GRPC.Server.send_reply(stream, ActionProtocol.decode(ctx, r)) - # end) - # |> Stream.run() - # else - # {:error, _reason} = err -> err - # end - stream_result = with {:ok, conn} <- get_connection(), client_stream = ActionClient.handle_streamed(conn), @@ -79,19 +65,22 @@ defmodule MassaProxy.Runtime.Middleware do {:ok, %ActionResponse{side_effects: effects} = command} -> Logger.debug("Consumer Stream result: #{inspect(command)}") - case process_command(nil, context, command) do - {:ok, result} -> - {:ok, result} + result = + case process_command(nil, context, command) do + {:ok, result} -> + {:ok, result} - {:error, reason} -> - {:error, "Failure on process client stream #{inspect(reason)}"} - end + {:error, reason} -> + {:error, "Failure on process command #{inspect(reason)}"} + end handle_effects(effects) + result {:error, reason} -> {:error, "Failure on process client stream #{inspect(reason)}"} end) + |> Enum.to_list() {:ok, consumer_stream} else diff --git a/apps/massa_proxy/lib/massa_proxy/util.ex b/apps/massa_proxy/lib/massa_proxy/util.ex index 6a13bf9..af5113f 100644 --- a/apps/massa_proxy/lib/massa_proxy/util.ex +++ b/apps/massa_proxy/lib/massa_proxy/util.ex @@ -157,8 +157,8 @@ defmodule MassaProxy.Util do def get_connection(), do: GRPC.Stub.connect(get_address(is_uds_enable?()), - interceptors: [GRPC.Logger.Client], - adapter_opts: %{http2_opts: %{keepalive: 10000}} + interceptors: [GRPC.Logger.Client] + # adapter_opts: %{http2_opts: %{keepalive: 10000}} ) def get_uds_address(), From 393d526e99131495a94f81629a710ac7f2b14672 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Mon, 14 Feb 2022 20:27:08 -0300 Subject: [PATCH 10/19] Fixed #112 --- .../runtime/grpc/protocol/action/protocol.ex | 18 ++++++++++++++++-- .../lib/massa_proxy/runtime/middleware.ex | 6 +----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex index 86a8425..a1ba218 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex @@ -38,10 +38,24 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Protocol do end @spec build_stream(t()) :: Enumerable.t() - def build_stream(%{message: msgs} = state) do + def build_stream( + %{service_name: service_name, original_method: original_method, message: msgs} = state + ) do + # The first message in will contain the request metadata, including the + # service name and command name. It will not have an associated payload set. + # This will be followed by zero to many messages in with a payload + init_command = [ + ActionCommand.new( + service_name: service_name, + name: original_method, + metadata: Metadata.new() + ) + ] + + init_command + |> Stream.concat(msgs) # Need to signal end_of_stream so attach a token to # end of the stream so that we can call `GRPC.Stub.end_stream` - msgs |> Stream.concat([:halt]) |> Stream.transform({:pre_send, state}, &transform/2) end diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex index c1da0c6..a7ce990 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -159,14 +159,10 @@ defmodule MassaProxy.Runtime.Middleware do defp run_stream(client_stream, messages) do Logger.debug("Running client stream #{inspect(messages)}") - Stream.filter(messages, &is_command_valid?(&1)) + messages |> Stream.map(&send_stream_msg(client_stream, &1)) end - defp is_command_valid?(:halt), do: true - defp is_command_valid?(%Cloudstate.Action.ActionCommand{payload: nil}), do: false - defp is_command_valid?(%Cloudstate.Action.ActionCommand{payload: _payload}), do: true - defp send_stream_msg(client_stream, :halt) do Logger.debug("send_stream_msg :halt") GRPC.Stub.end_stream(client_stream) From bd49a8fdf0980c49a6965589777ff790cec05907 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Wed, 16 Feb 2022 15:40:40 -0300 Subject: [PATCH 11/19] Router events --- .../cluster/entity/entity_registry.ex | 64 +++++++++- .../lib/massa_proxy/protocol/router.ex | 114 ++++++++++++++---- .../runtime/grpc/protocol/action/protocol.ex | 4 +- .../grpc/protocol/action/stream_handler.ex | 3 +- .../grpc/protocol/action/unary_handler.ex | 2 +- .../grpc/protocol/discovery/manager.ex | 2 + .../lib/massa_proxy/runtime/middleware.ex | 49 ++++++-- apps/massa_proxy/lib/massa_proxy/util.ex | 14 ++- 8 files changed, 207 insertions(+), 45 deletions(-) diff --git a/apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry.ex b/apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry.ex index 1b8dc22..d9c0e18 100644 --- a/apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry.ex +++ b/apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry.ex @@ -66,17 +66,71 @@ defmodule MassaProxy.Entity.EntityRegistry do {:noreply, new_state} end + defp get_simple_name(service_name), do: String.split(service_name, ".") |> List.last() + @impl true - def handle_call({:get, entity_type}, _from, state) do + def handle_call({:get, entity_type, service_name, method_name}, _from, state) do nodes = state |> Enum.reduce([], fn {key, value}, acc -> for entity <- value do - if entity.entity_type == entity_type do - [key] ++ acc + Logger.debug("Acumulator #{inspect(acc)}") + + if entity.entity_type == entity_type and entity.service_name == service_name do + service_data = + Enum.map(entity.services, fn service -> + Logger.debug("Found service #{inspect(service)}") + + if service.name == get_simple_name(service_name) do + Logger.debug("Inside if service") + + method_metadata = + Enum.map(service.methods, fn method -> + Logger.debug("Found method #{inspect(method)}") + + if method.name == method_name do + Logger.debug("Inside if method") + + %{ + entity_type: entity_type, + service_name: get_simple_name(service_name), + full_service_name: service_name, + persistence_id: entity.persistence_id, + method_name: method.name, + input_type: method.input_type, + output_type: method.output_type, + stream_in: method.stream_in, + stream_out: method.stream_out, + streamed: method.streamed, + unary: method.unary + } + + # else + # %{} + end + end) + |> List.flatten() + |> Enum.uniq() + + # |> List.first() + + Logger.debug("Found method metadata #{inspect(method_metadata)}") + method_metadata + # else + # %{} + end + end) + |> List.flatten() + |> Enum.uniq() + + Logger.debug("Found service data #{inspect(service_data)}") + acumulator = [%{node: key, entity: service_data}] ++ acc + Logger.debug("Found Acumulator data #{inspect(acumulator)}") + acumulator end end end) + |> Enum.filter(&is_nil/1) |> List.flatten() |> Enum.uniq() @@ -160,8 +214,8 @@ defmodule MassaProxy.Entity.EntityRegistry do end # fetch current entities of the service - def lookup(entity_type) do - GenServer.call(__MODULE__, {:get, entity_type}) + def lookup(entity_type, service_name, method_name) do + GenServer.call(__MODULE__, {:get, entity_type, service_name, method_name}) end defp include_entities(state, message), do: Map.merge(state, message) diff --git a/apps/massa_proxy/lib/massa_proxy/protocol/router.ex b/apps/massa_proxy/lib/massa_proxy/protocol/router.ex index 7745029..7bba39a 100644 --- a/apps/massa_proxy/lib/massa_proxy/protocol/router.ex +++ b/apps/massa_proxy/lib/massa_proxy/protocol/router.ex @@ -3,35 +3,101 @@ defmodule MassaProxy.Protocol.Router do Dispatch the given `mod`, `fun`, `args` request to the appropriate node based on the `bucket`. """ - def route(bucket, mod, fun, args) do - # Get the first byte of the binary - first = :binary.first(bucket) - - # Try to find an entry in the table() or raise - entry = - Enum.find(table(), fn {enum, _node} -> - first in enum - end) || no_entry_error(bucket) - - # If the entry node is the current node - if elem(entry, 1) == node() do - apply(mod, fun, args) + require Logger + + alias MassaProxy.Entity.EntityRegistry + alias MassaProxy.TaskSupervisor + + @timeout 10000 + + def route( + entity_type, + service_name, + command_name, + input_type, + async \\ false, + mod, + fun, + payload + ) do + with node_entities <- EntityRegistry.lookup(entity_type, service_name, command_name) do + Logger.debug("Routing request to #{inspect(node_entities)}") + + targets = + Enum.map(node_entities, fn %{node: member, entity: entity} = _node_entity -> + if member == node() do + {:local, node(), entity} + else + {:remote, member, entity} + end + end) + |> List.flatten() + + result = + case Enum.find(targets, fn target -> match?({:local, _, _}, target) end) do + {:local, _member, entity} -> + Logger.debug("Local: #{entity}") + + payload = %{ + payload + | entity_type: entity_type, + service_name: service_name, + request_type: "unary", + original_method: command_name, + input_type: input_type, + output_type: "", + persistence_id: nil, + message: payload, + stream: nil + } + + apply(mod, fun, [payload]) + + nil -> + Logger.debug("Remote: #{targets}") + {:remote, member, entity} = List.first(targets) + + Logger.debug("Remote: #{entity}") + + payload = %{ + payload + | entity_type: entity_type, + service_name: service_name, + request_type: "unary", + original_method: command_name, + input_type: input_type, + output_type: "", + persistence_id: nil, + message: payload, + stream: nil + } + + call(member, async, mod, fun, [payload]) + end + + result else - {KV.RouterTasks, elem(entry, 1)} - |> Task.Supervisor.async(KV.Router, :route, [bucket, mod, fun, args]) - |> Task.await() + [] -> {:unrouted, :not_found} end end - defp no_entry_error(bucket) do - raise "could not find entry for #{inspect(bucket)} in table #{inspect(table())}" + defp call(node, true, mod, fun, args) do + Logger.debug("Invoking remote call on node #{inspect(node)}") + + pid = + Node.spawn(node, fn -> + Kernel.apply(__MODULE__, :route, [mod, fun, args]) + end) + + {:routed, :fire_and_forget, pid} end - @doc """ - The routing table. - """ - def table do - # Replace computer-name with your local machine name - [{?a..?m, :"foo@computer-name"}, {?n..?z, :"bar@computer-name"}] + defp call(node, false, mod, fun, args) do + remote_result = + {TaskSupervisor, node} + |> Task.Supervisor.async(__MODULE__, :route, [mod, fun, args]) + |> Task.await(@timeout) + + {:routed, remote_result} end end diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex index a1ba218..a1ea022 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex @@ -75,7 +75,9 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Protocol do {[command], acc} end - defp build_payload(%{input_type: input_type, message: msg}), + defp build_payload(%{input_type: input_type, message: msg}) when is_binary(input_type), do: msg + + defp build_payload(%{input_type: input_type, message: msg}) when is_atom(input_type), do: Any.new( type_url: Util.get_type_url(input_type), diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex index 9f86a50..c7d5b9e 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex @@ -12,11 +12,10 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler do def handle_streamed(%{stream: stream} = ctx) do with messages <- ActionProtocol.build_stream(ctx), - {:ok, consumer_stream} <- Middleware.streamed_req(ctx, messages) do + {:ok, consumer_stream} <- Middleware.streamed(ctx, messages) do consumer_stream |> Stream.each(fn {:ok, r} -> - Logger.info("Decode -----> #{inspect(r)}") GRPC.Server.send_reply(stream, ActionProtocol.decode(ctx, r)) {:error, _reason} = err -> diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex index 19e51f5..eb681b7 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex @@ -9,7 +9,7 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Unary.Handler do def handle_unary(ctx) do response = with message <- ActionProtocol.build_msg(ctx), - {:ok, response} <- Middleware.unary_req(ctx, message) do + {:ok, response} <- Middleware.unary(ctx, message) do ActionProtocol.decode(ctx, response) else {:error, reason} -> {:error, "Failure to make unary request #{inspect(reason)}"} diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/discovery/manager.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/discovery/manager.ex index 7e58ca3..1f2d9f7 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/discovery/manager.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/discovery/manager.ex @@ -77,6 +77,8 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Discovery.Manager do end defp register_entity(entity) do + Logger.debug("Registering entity #{inspect(entity)}") + case entity.entity_type do "cloudstate.eventsourced.EventSourced" -> MassaProxy.Entity.EntityRegistry.register("EventSourced", [entity]) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex index a7ce990..f535ae7 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -6,8 +6,10 @@ defmodule MassaProxy.Runtime.Middleware do use GenServer require Logger - alias Cloudstate.Action.ActionResponse + alias Cloudstate.{Action.ActionResponse, SideEffect} alias Cloudstate.Action.ActionProtocol.Stub, as: ActionClient + alias MassaProxy.Protocol.Router + alias MassaProxy.Runtime.Grpc.Server.Dispatcher import MassaProxy.Util, only: [get_connection: 0] @@ -32,7 +34,7 @@ defmodule MassaProxy.Runtime.Middleware do {:ok, %ActionResponse{side_effects: effects} = commands} <- ActionClient.handle_unary(channel, message), {:ok, result} <- process_command(nil, context, commands) do - handle_effects(effects) + handle_effects(context, effects) {:ok, result} else {:error, reason} -> {:error, "Failure to make unary request #{inspect(reason)}"} @@ -74,7 +76,7 @@ defmodule MassaProxy.Runtime.Middleware do {:error, "Failure on process command #{inspect(reason)}"} end - handle_effects(effects) + handle_effects(context, effects) result {:error, reason} -> @@ -104,11 +106,11 @@ defmodule MassaProxy.Runtime.Middleware do {:noreply, state} end - def unary_req(%{entity_type: entity_type} = ctx, message) do + def unary(%{entity_type: entity_type} = ctx, message) do GenServer.call(get_name(entity_type), {:handle_unary, %{context: ctx, payload: message}}) end - def streamed_req(%{entity_type: entity_type} = ctx, messages) do + def streamed(%{entity_type: entity_type} = ctx, messages) do GenServer.call(get_name(entity_type), {:handle_streamed, %{context: ctx, payload: messages}}) end @@ -140,12 +142,41 @@ defmodule MassaProxy.Runtime.Middleware do {:ok, message} end - defp handle_effects([]), do: {:ok, []} - - defp handle_effects(effects) when is_list(effects) and length(effects) > 0 do + defp handle_effects(_ctx, []), do: {:ok, []} + + defp handle_effects( + %{entity_type: entity_type} = _ctx, + effects + ) + when is_list(effects) and length(effects) > 0 do + Enum.each(effects, fn %SideEffect{ + service_name: service_name, + command_name: command_name, + synchronous: synchronous, + payload: %Google.Protobuf.Any{type_url: input_type} = payload + } = effect -> + Logger.debug( + "Handling side effect #{inspect(effect)}} with command name: #{command_name} and input type: #{input_type}" + ) + + payload = %{ + message: payload + } + + Router.route( + entity_type, + service_name, + command_name, + input_type, + !synchronous, + Dispatcher, + :dispatch, + payload + ) + end) end - defp handle_effects(_), do: {:ok, []} + defp handle_effects(_ctx, _), do: {:ok, []} defp get_name(entity_type) do mod = diff --git a/apps/massa_proxy/lib/massa_proxy/util.ex b/apps/massa_proxy/lib/massa_proxy/util.ex index af5113f..377cdef 100644 --- a/apps/massa_proxy/lib/massa_proxy/util.ex +++ b/apps/massa_proxy/lib/massa_proxy/util.ex @@ -117,7 +117,15 @@ defmodule MassaProxy.Util do evt_ext end - def get_type_url(type) do + def get_type_url(type) when is_binary(type) do + if String.contains?(type, "type.googleapis.com/") do + type + else + raise "Invalid type: #{type}" + end + end + + def get_type_url(type) when is_atom(type) do parts = type |> to_string @@ -157,8 +165,8 @@ defmodule MassaProxy.Util do def get_connection(), do: GRPC.Stub.connect(get_address(is_uds_enable?()), - interceptors: [GRPC.Logger.Client] - # adapter_opts: %{http2_opts: %{keepalive: 10000}} + interceptors: [GRPC.Logger.Client], + adapter_opts: %{http2_opts: %{keepalive: 10000}} ) def get_uds_address(), From e619b0c2e72bce4ee02897b959ba2f4347b2dbd7 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Wed, 16 Feb 2022 19:58:58 -0300 Subject: [PATCH 12/19] Added streamed side effects --- .../cluster/entity/entity_registry.ex | 37 +++------- .../lib/massa_proxy/protocol/router.ex | 71 +++++++++++-------- .../runtime/grpc/protocol/action/protocol.ex | 15 +++- .../grpc/protocol/action/stream_handler.ex | 6 +- .../grpc/protocol/action/unary_handler.ex | 2 +- .../lib/massa_proxy/runtime/middleware.ex | 70 ++++++++++++------ .../lib/massa_proxy/server/grpc_server.ex | 14 +--- apps/massa_proxy/lib/massa_proxy/util.ex | 12 ++++ config/config.exs | 3 +- config/prod.exs | 2 +- 10 files changed, 137 insertions(+), 95 deletions(-) diff --git a/apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry.ex b/apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry.ex index d9c0e18..1f9a0db 100644 --- a/apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry.ex +++ b/apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry.ex @@ -74,64 +74,43 @@ defmodule MassaProxy.Entity.EntityRegistry do state |> Enum.reduce([], fn {key, value}, acc -> for entity <- value do - Logger.debug("Acumulator #{inspect(acc)}") - if entity.entity_type == entity_type and entity.service_name == service_name do service_data = Enum.map(entity.services, fn service -> - Logger.debug("Found service #{inspect(service)}") - if service.name == get_simple_name(service_name) do - Logger.debug("Inside if service") - method_metadata = Enum.map(service.methods, fn method -> - Logger.debug("Found method #{inspect(method)}") - if method.name == method_name do - Logger.debug("Inside if method") - %{ entity_type: entity_type, service_name: get_simple_name(service_name), full_service_name: service_name, persistence_id: entity.persistence_id, method_name: method.name, - input_type: method.input_type, - output_type: method.output_type, - stream_in: method.stream_in, - stream_out: method.stream_out, - streamed: method.streamed, - unary: method.unary + method: method } - - # else - # %{} + else + %{} end end) |> List.flatten() |> Enum.uniq() + |> List.first() - # |> List.first() - - Logger.debug("Found method metadata #{inspect(method_metadata)}") method_metadata - # else - # %{} + else + %{} end end) |> List.flatten() |> Enum.uniq() - Logger.debug("Found service data #{inspect(service_data)}") - acumulator = [%{node: key, entity: service_data}] ++ acc - Logger.debug("Found Acumulator data #{inspect(acumulator)}") - acumulator + [%{node: key, entity: service_data}] ++ acc end end end) - |> Enum.filter(&is_nil/1) |> List.flatten() + |> Enum.reject(&is_nil/1) |> Enum.uniq() if Enum.all?(nodes, &is_nil/1) do diff --git a/apps/massa_proxy/lib/massa_proxy/protocol/router.ex b/apps/massa_proxy/lib/massa_proxy/protocol/router.ex index 7bba39a..9955f82 100644 --- a/apps/massa_proxy/lib/massa_proxy/protocol/router.ex +++ b/apps/massa_proxy/lib/massa_proxy/protocol/router.ex @@ -7,6 +7,7 @@ defmodule MassaProxy.Protocol.Router do alias MassaProxy.Entity.EntityRegistry alias MassaProxy.TaskSupervisor + alias MassaProxy.Util @timeout 10000 @@ -18,11 +19,9 @@ defmodule MassaProxy.Protocol.Router do async \\ false, mod, fun, - payload + %{message: payload} = message ) do with node_entities <- EntityRegistry.lookup(entity_type, service_name, command_name) do - Logger.debug("Routing request to #{inspect(node_entities)}") - targets = Enum.map(node_entities, fn %{node: member, entity: entity} = _node_entity -> if member == node() do @@ -35,44 +34,42 @@ defmodule MassaProxy.Protocol.Router do result = case Enum.find(targets, fn target -> match?({:local, _, _}, target) end) do - {:local, _member, entity} -> - Logger.debug("Local: #{entity}") + {:local, _member, entities} -> + entity = List.first(entities) - payload = %{ - payload + message = %{ + message | entity_type: entity_type, - service_name: service_name, - request_type: "unary", - original_method: command_name, + service_name: entity.full_service_name, + request_type: Util.get_type(entity.method), + original_method: entity.method_name, input_type: input_type, - output_type: "", - persistence_id: nil, + output_type: to_module(entity.method.output_type), + persistence_id: entity.persistence_id, message: payload, stream: nil } - apply(mod, fun, [payload]) + apply(mod, fun, [message]) nil -> - Logger.debug("Remote: #{targets}") - {:remote, member, entity} = List.first(targets) - - Logger.debug("Remote: #{entity}") + {:remote, member, entities} = List.first(targets) + entity = List.first(entities) - payload = %{ - payload + message = %{ + message | entity_type: entity_type, - service_name: service_name, - request_type: "unary", - original_method: command_name, + service_name: entity.full_service_name, + request_type: Util.get_type(entity.method), + original_method: entity.method_name, input_type: input_type, - output_type: "", - persistence_id: nil, + output_type: to_module(entity.method.output_type), + persistence_id: entity.persistence_id, message: payload, stream: nil } - call(member, async, mod, fun, [payload]) + call(member, async, mod, fun, message) end result @@ -82,22 +79,40 @@ defmodule MassaProxy.Protocol.Router do end defp call(node, true, mod, fun, args) do - Logger.debug("Invoking remote call on node #{inspect(node)}") + Logger.info("Invoking async remote call on node #{inspect(node)}") pid = Node.spawn(node, fn -> - Kernel.apply(__MODULE__, :route, [mod, fun, args]) + Kernel.apply(mod, fun, [args]) end) {:routed, :fire_and_forget, pid} end defp call(node, false, mod, fun, args) do + Logger.info("Invoking sync remote call on node #{inspect(node)}") + remote_result = {TaskSupervisor, node} - |> Task.Supervisor.async(__MODULE__, :route, [mod, fun, args]) + |> Task.Supervisor.async(mod, fun, [args]) |> Task.await(@timeout) {:routed, remote_result} end + + defp to_module(name) do + pre_mod = + name + |> String.split(".") + |> Enum.reject(fn elem -> if elem == "", do: true end) + |> Enum.map(&String.capitalize(&1)) + + mod = + ["Elixir"] + |> Enum.concat(pre_mod) + |> Enum.join(".") + |> String.to_atom() + + mod + end end diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex index a1ea022..491e9cf 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex @@ -1,4 +1,6 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Protocol do + require Logger + alias Cloudstate.{Action.ActionCommand, Action.ActionResponse, Metadata} alias Google.Protobuf.Any alias MassaProxy.Util @@ -84,5 +86,16 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Protocol do value: input_type.encode(msg) ) - defp decode_payload(output_mod, %{payload: %Any{value: bin}}), do: output_mod.decode(bin) + # defp decode_payload(output_mod, %{payload: %Any{value: bin}}) when is_binary(output_mod) do + # mod = + # Any.new( + # type_url: Util.get_type_url("type.googleapis.com/cloudstate.tck.model.action.Response"), + # value: bin + # ) + + # mod.decode(bin) + # end + + defp decode_payload(output_mod, %{payload: %Any{value: bin}}) when is_atom(output_mod), + do: output_mod.decode(bin) end diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex index c7d5b9e..7a4068e 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex @@ -5,6 +5,7 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler do require Logger alias Cloudstate.Action.ActionProtocol.Stub, as: ActionClient + alias Google.Protobuf.Empty alias MassaProxy.Runtime.Grpc.Protocol.Action.Protocol, as: ActionProtocol alias MassaProxy.Runtime.Middleware @@ -15,7 +16,10 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler do {:ok, consumer_stream} <- Middleware.streamed(ctx, messages) do consumer_stream |> Stream.each(fn - {:ok, r} -> + {:ok, %Cloudstate.Action.ActionResponse{response: nil}} -> + GRPC.Server.send_reply(stream, Empty.new()) + + {:ok, %Cloudstate.Action.ActionResponse{response: _response} = r} -> GRPC.Server.send_reply(stream, ActionProtocol.decode(ctx, r)) {:error, _reason} = err -> diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex index eb681b7..f471131 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/unary_handler.ex @@ -15,7 +15,7 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Unary.Handler do {:error, reason} -> {:error, "Failure to make unary request #{inspect(reason)}"} end - Logger.debug(fn -> "User function response #{inspect(response)}" end) + Logger.debug(fn -> "Unary.Handler User function response #{inspect(response)}" end) response end diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex index f535ae7..0683136 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -9,7 +9,7 @@ defmodule MassaProxy.Runtime.Middleware do alias Cloudstate.{Action.ActionResponse, SideEffect} alias Cloudstate.Action.ActionProtocol.Stub, as: ActionClient alias MassaProxy.Protocol.Router - alias MassaProxy.Runtime.Grpc.Server.Dispatcher + alias MassaProxy.Runtime.Grpc.Protocol.Action.Protocol, as: ActionProtocol import MassaProxy.Util, only: [get_connection: 0] @@ -34,13 +34,13 @@ defmodule MassaProxy.Runtime.Middleware do {:ok, %ActionResponse{side_effects: effects} = commands} <- ActionClient.handle_unary(channel, message), {:ok, result} <- process_command(nil, context, commands) do - handle_effects(context, effects) + call_effects(context, effects) {:ok, result} else {:error, reason} -> {:error, "Failure to make unary request #{inspect(reason)}"} end - Logger.debug("User function response #{inspect(result)}") + Logger.debug("Middleware User function response #{inspect(result)}") {:reply, result, state} end @@ -57,10 +57,6 @@ defmodule MassaProxy.Runtime.Middleware do client_stream = ActionClient.handle_streamed(conn), :ok <- run_stream(client_stream, messages) |> Stream.run(), {:ok, consumer_stream} <- GRPC.Stub.recv(client_stream) do - Logger.debug( - "Commands: #{inspect(consumer_stream)} Client Stream: #{inspect(client_stream)}" - ) - consumer_stream = consumer_stream |> Stream.map(fn @@ -76,7 +72,7 @@ defmodule MassaProxy.Runtime.Middleware do {:error, "Failure on process command #{inspect(reason)}"} end - handle_effects(context, effects) + call_effects(context, effects) result {:error, reason} -> @@ -99,6 +95,24 @@ defmodule MassaProxy.Runtime.Middleware do {:noreply, state} end + @impl true + def handle_cast({:handle_effect, ctx}, state) do + with message <- ActionProtocol.build_msg(ctx), + {:ok, channel} <- get_connection(), + {:ok, %ActionResponse{} = commands} <- + ActionClient.handle_unary(channel, message), + {:ok, result} <- process_command(nil, ctx, commands) do + Logger.debug( + "Handle effects User function response #{inspect(commands)}. With commands result #{inspect(result)}" + ) + else + {:error, reason} -> + Logger.warn("Failure to make unary request #{inspect(reason)}") + end + + {:noreply, state} + end + @impl true def handle_info(msg, state) do Logger.notice("Received unexpected message: #{inspect(msg)}") @@ -114,6 +128,10 @@ defmodule MassaProxy.Runtime.Middleware do GenServer.call(get_name(entity_type), {:handle_streamed, %{context: ctx, payload: messages}}) end + def effect(%{entity_type: entity_type} = ctx) do + GenServer.cast(get_name(entity_type), {:handle_effect, ctx}) + end + defp process_command( _command_processor, _context, @@ -138,13 +156,21 @@ defmodule MassaProxy.Runtime.Middleware do {:ok, message} end + defp process_command( + _command_processor, + _context, + %ActionResponse{response: nil} = _message + ) do + {:ok, %ActionResponse{}} + end + defp process_command(nil, _context, message) do {:ok, message} end - defp handle_effects(_ctx, []), do: {:ok, []} + defp call_effects(_ctx, []), do: {:ok, []} - defp handle_effects( + defp call_effects( %{entity_type: entity_type} = _ctx, effects ) @@ -159,8 +185,16 @@ defmodule MassaProxy.Runtime.Middleware do "Handling side effect #{inspect(effect)}} with command name: #{command_name} and input type: #{input_type}" ) - payload = %{ - message: payload + message = %{ + message: payload, + entity_type: nil, + service_name: nil, + request_type: nil, + original_method: nil, + input_type: nil, + output_type: nil, + persistence_id: nil, + stream: nil } Router.route( @@ -169,14 +203,14 @@ defmodule MassaProxy.Runtime.Middleware do command_name, input_type, !synchronous, - Dispatcher, - :dispatch, - payload + __MODULE__, + :effect, + message ) end) end - defp handle_effects(_ctx, _), do: {:ok, []} + defp call_effects(_ctx, _), do: {:ok, []} defp get_name(entity_type) do mod = @@ -188,19 +222,15 @@ defmodule MassaProxy.Runtime.Middleware do end defp run_stream(client_stream, messages) do - Logger.debug("Running client stream #{inspect(messages)}") - messages |> Stream.map(&send_stream_msg(client_stream, &1)) end defp send_stream_msg(client_stream, :halt) do - Logger.debug("send_stream_msg :halt") GRPC.Stub.end_stream(client_stream) end defp send_stream_msg(client_stream, msg) do - Logger.debug("send_stream_msg #{inspect(msg)}") GRPC.Stub.send_request(client_stream, msg, []) end end diff --git a/apps/massa_proxy/lib/massa_proxy/server/grpc_server.ex b/apps/massa_proxy/lib/massa_proxy/server/grpc_server.ex index 03f5645..4f80b02 100644 --- a/apps/massa_proxy/lib/massa_proxy/server/grpc_server.ex +++ b/apps/massa_proxy/lib/massa_proxy/server/grpc_server.ex @@ -250,18 +250,6 @@ defmodule MassaProxy.Server.GrpcServer do defp get_request_type(services), do: Enum.reduce(services.methods, %{}, fn method, acc -> - Map.put(acc, Util.normalize_method_name(method.name), get_type(method)) + Map.put(acc, Util.normalize_method_name(method.name), Util.get_type(method)) end) - - defp get_type(method) do - type = - cond do - method.unary == true -> "unary" - method.streamed == true -> "streamed" - method.stream_in == true -> "stream_in" - method.stream_out == true -> "stream_out" - end - - type - end end diff --git a/apps/massa_proxy/lib/massa_proxy/util.ex b/apps/massa_proxy/lib/massa_proxy/util.ex index 377cdef..f818bf6 100644 --- a/apps/massa_proxy/lib/massa_proxy/util.ex +++ b/apps/massa_proxy/lib/massa_proxy/util.ex @@ -117,6 +117,18 @@ defmodule MassaProxy.Util do evt_ext end + def get_type(method) do + type = + cond do + method.unary == true -> "unary" + method.streamed == true -> "streamed" + method.stream_in == true -> "stream_in" + method.stream_out == true -> "stream_out" + end + + type + end + def get_type_url(type) when is_binary(type) do if String.contains?(type, "type.googleapis.com/") do type diff --git a/config/config.exs b/config/config.exs index 55c6b46..cf4cc04 100644 --- a/config/config.exs +++ b/config/config.exs @@ -44,7 +44,8 @@ config :massa_proxy, proxy_http_port: System.get_env("PROXY_HTTP_PORT", "9001") |> String.to_integer(), user_function_host: System.get_env("USER_FUNCTION_HOST", "127.0.0.1"), user_function_port: System.get_env("USER_FUNCTION_PORT", "8080") |> String.to_integer(), - user_function_uds_enable: System.get_env("PROXY_UDS_MODE", "false") |> String.to_existing_atom(), + user_function_uds_enable: + System.get_env("PROXY_UDS_MODE", "false") |> String.to_existing_atom(), user_function_sock_addr: System.get_env("PROXY_UDS_ADDRESS", "/var/run/cloudstate.sock"), heartbeat_interval: System.get_env("PROXY_HEARTBEAT_INTERVAL", "240000") |> String.to_integer() diff --git a/config/prod.exs b/config/prod.exs index 6fb52d6..46ef105 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -4,7 +4,7 @@ import Config config :logger, backends: [:console], compile_time_purge_matching: [ - [level_lower_than: :info] + [level_lower_than: :debug] ] config :protobuf, extensions: :enabled From 4e68b8bf7c8b9688d54780764cfdee06cb45d2a6 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Wed, 16 Feb 2022 20:31:12 -0300 Subject: [PATCH 13/19] Refactor. New structure --- Makefile | 2 +- apps/eigr_protocol/.formatter.exs | 4 ++ apps/eigr_protocol/.gitignore | 26 ++++++++++++ apps/eigr_protocol/README.md | 21 ++++++++++ apps/eigr_protocol/lib/eigr_protocol.ex | 18 ++++++++ apps/eigr_protocol/mix.exs | 33 +++++++++++++++ .../eigr_protocol/test/eigr_protocol_test.exs | 8 ++++ apps/eigr_protocol/test/test_helper.exs | 1 + apps/massa_proxy/mix.exs | 22 ++++------ apps/runtime/.formatter.exs | 4 ++ apps/runtime/.gitignore | 26 ++++++++++++ apps/runtime/README.md | 21 ++++++++++ apps/runtime/lib/runtime.ex | 18 ++++++++ apps/runtime/mix.exs | 41 +++++++++++++++++++ apps/runtime/test/runtime_test.exs | 8 ++++ apps/runtime/test/test_helper.exs | 1 + apps/runtime_grpc/.formatter.exs | 4 ++ apps/runtime_grpc/.gitignore | 26 ++++++++++++ apps/runtime_grpc/README.md | 21 ++++++++++ apps/runtime_grpc/lib/runtime_grpc.ex | 18 ++++++++ apps/runtime_grpc/mix.exs | 31 ++++++++++++++ apps/runtime_grpc/test/runtime_grpc_test.exs | 8 ++++ apps/runtime_grpc/test/test_helper.exs | 1 + apps/runtime_wasm/.formatter.exs | 4 ++ apps/runtime_wasm/.gitignore | 26 ++++++++++++ apps/runtime_wasm/README.md | 21 ++++++++++ apps/runtime_wasm/lib/runtime_wasm.ex | 18 ++++++++ apps/runtime_wasm/mix.exs | 33 +++++++++++++++ apps/runtime_wasm/test/runtime_wasm_test.exs | 8 ++++ apps/runtime_wasm/test/test_helper.exs | 1 + apps/store/.formatter.exs | 4 ++ apps/store/.gitignore | 26 ++++++++++++ apps/store/README.md | 21 ++++++++++ apps/store/lib/store.ex | 18 ++++++++ apps/store/mix.exs | 33 +++++++++++++++ apps/store/test/store_test.exs | 8 ++++ apps/store/test/test_helper.exs | 1 + apps/store_inmemory/.formatter.exs | 4 ++ apps/store_inmemory/.gitignore | 26 ++++++++++++ apps/store_inmemory/README.md | 21 ++++++++++ apps/store_inmemory/lib/store_inmemory.ex | 18 ++++++++ apps/store_inmemory/mix.exs | 33 +++++++++++++++ .../test/store_inmemory_test.exs | 8 ++++ apps/store_inmemory/test/test_helper.exs | 1 + 44 files changed, 680 insertions(+), 16 deletions(-) create mode 100644 apps/eigr_protocol/.formatter.exs create mode 100644 apps/eigr_protocol/.gitignore create mode 100644 apps/eigr_protocol/README.md create mode 100644 apps/eigr_protocol/lib/eigr_protocol.ex create mode 100644 apps/eigr_protocol/mix.exs create mode 100644 apps/eigr_protocol/test/eigr_protocol_test.exs create mode 100644 apps/eigr_protocol/test/test_helper.exs create mode 100644 apps/runtime/.formatter.exs create mode 100644 apps/runtime/.gitignore create mode 100644 apps/runtime/README.md create mode 100644 apps/runtime/lib/runtime.ex create mode 100644 apps/runtime/mix.exs create mode 100644 apps/runtime/test/runtime_test.exs create mode 100644 apps/runtime/test/test_helper.exs create mode 100644 apps/runtime_grpc/.formatter.exs create mode 100644 apps/runtime_grpc/.gitignore create mode 100644 apps/runtime_grpc/README.md create mode 100644 apps/runtime_grpc/lib/runtime_grpc.ex create mode 100644 apps/runtime_grpc/mix.exs create mode 100644 apps/runtime_grpc/test/runtime_grpc_test.exs create mode 100644 apps/runtime_grpc/test/test_helper.exs create mode 100644 apps/runtime_wasm/.formatter.exs create mode 100644 apps/runtime_wasm/.gitignore create mode 100644 apps/runtime_wasm/README.md create mode 100644 apps/runtime_wasm/lib/runtime_wasm.ex create mode 100644 apps/runtime_wasm/mix.exs create mode 100644 apps/runtime_wasm/test/runtime_wasm_test.exs create mode 100644 apps/runtime_wasm/test/test_helper.exs create mode 100644 apps/store/.formatter.exs create mode 100644 apps/store/.gitignore create mode 100644 apps/store/README.md create mode 100644 apps/store/lib/store.ex create mode 100644 apps/store/mix.exs create mode 100644 apps/store/test/store_test.exs create mode 100644 apps/store/test/test_helper.exs create mode 100644 apps/store_inmemory/.formatter.exs create mode 100644 apps/store_inmemory/.gitignore create mode 100644 apps/store_inmemory/README.md create mode 100644 apps/store_inmemory/lib/store_inmemory.ex create mode 100644 apps/store_inmemory/mix.exs create mode 100644 apps/store_inmemory/test/store_inmemory_test.exs create mode 100644 apps/store_inmemory/test/test_helper.exs diff --git a/Makefile b/Makefile index 77bf7ea..0ba1d16 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -image=eigr/massa-proxy:0.1.36 +image=eigr/massa-proxy:1.0.0-PREVIEW port=8080 .PHONY: all clean diff --git a/apps/eigr_protocol/.formatter.exs b/apps/eigr_protocol/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/apps/eigr_protocol/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/apps/eigr_protocol/.gitignore b/apps/eigr_protocol/.gitignore new file mode 100644 index 0000000..7483f11 --- /dev/null +++ b/apps/eigr_protocol/.gitignore @@ -0,0 +1,26 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +eigr_protocol-*.tar + +# Temporary files, for example, from tests. +/tmp/ diff --git a/apps/eigr_protocol/README.md b/apps/eigr_protocol/README.md new file mode 100644 index 0000000..b14e6f0 --- /dev/null +++ b/apps/eigr_protocol/README.md @@ -0,0 +1,21 @@ +# EigrProtocol + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `eigr_protocol` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:eigr_protocol, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at . + diff --git a/apps/eigr_protocol/lib/eigr_protocol.ex b/apps/eigr_protocol/lib/eigr_protocol.ex new file mode 100644 index 0000000..1d7c917 --- /dev/null +++ b/apps/eigr_protocol/lib/eigr_protocol.ex @@ -0,0 +1,18 @@ +defmodule EigrProtocol do + @moduledoc """ + Documentation for `EigrProtocol`. + """ + + @doc """ + Hello world. + + ## Examples + + iex> EigrProtocol.hello() + :world + + """ + def hello do + :world + end +end diff --git a/apps/eigr_protocol/mix.exs b/apps/eigr_protocol/mix.exs new file mode 100644 index 0000000..563ce6f --- /dev/null +++ b/apps/eigr_protocol/mix.exs @@ -0,0 +1,33 @@ +defmodule EigrProtocol.MixProject do + use Mix.Project + + def project do + [ + app: :eigr_protocol, + version: "0.1.0", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.13", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}, + # {:sibling_app_in_umbrella, in_umbrella: true} + ] + end +end diff --git a/apps/eigr_protocol/test/eigr_protocol_test.exs b/apps/eigr_protocol/test/eigr_protocol_test.exs new file mode 100644 index 0000000..a62da0a --- /dev/null +++ b/apps/eigr_protocol/test/eigr_protocol_test.exs @@ -0,0 +1,8 @@ +defmodule EigrProtocolTest do + use ExUnit.Case + doctest EigrProtocol + + test "greets the world" do + assert EigrProtocol.hello() == :world + end +end diff --git a/apps/eigr_protocol/test/test_helper.exs b/apps/eigr_protocol/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/apps/eigr_protocol/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/apps/massa_proxy/mix.exs b/apps/massa_proxy/mix.exs index 068601f..d32bbf1 100644 --- a/apps/massa_proxy/mix.exs +++ b/apps/massa_proxy/mix.exs @@ -31,21 +31,16 @@ defmodule MassaProxy.MixProject do defp deps do [ # Base deps - {:bakeware, "~> 0.2"}, {:cloudstate_protocol, in_umbrella: true}, - {:injectx, "~> 0.1"}, - {:wasmex, "~> 0.5"}, - {:toml, "~> 0.6", override: true}, - {:flow, "~> 1.0"}, + {:eigr_protocol, in_umbrella: true}, + {:runtime, in_umbrella: true}, + {:runtime_grpc, in_umbrella: true}, + {:runtime_wasm, in_umbrella: true}, + {:store, in_umbrella: true}, + {:store_inmemory, in_umbrella: true}, + {:bakeware, "~> 0.2"}, {:vapor, "~> 0.10"}, - # Grpc deps - {:protobuf, "~> 0.9.0", override: true}, - {:grpc, github: "elixir-grpc/grpc", override: true}, - {:cowlib, "~> 2.11", override: true}, - {:grpc_prometheus, "~> 0.1"}, - {:jason, "~> 1.2"}, - # Cluster deps {:libcluster, "~> 3.3"}, {:horde, "~> 0.8"}, @@ -56,9 +51,6 @@ defmodule MassaProxy.MixProject do # Observability deps {:ex_ray, "~> 0.1"}, {:hackney, "~> 1.16"}, - {:prometheus, "~> 4.6"}, - {:prometheus_plugs, "~> 1.1"}, - {:telemetry, "~> 0.4.3"}, # Http facilities {:plug_cowboy, "~> 2.3"}, diff --git a/apps/runtime/.formatter.exs b/apps/runtime/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/apps/runtime/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/apps/runtime/.gitignore b/apps/runtime/.gitignore new file mode 100644 index 0000000..ed71b30 --- /dev/null +++ b/apps/runtime/.gitignore @@ -0,0 +1,26 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +runtime-*.tar + +# Temporary files, for example, from tests. +/tmp/ diff --git a/apps/runtime/README.md b/apps/runtime/README.md new file mode 100644 index 0000000..ed263d1 --- /dev/null +++ b/apps/runtime/README.md @@ -0,0 +1,21 @@ +# Runtime + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `runtime` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:runtime, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at . + diff --git a/apps/runtime/lib/runtime.ex b/apps/runtime/lib/runtime.ex new file mode 100644 index 0000000..cfc98fb --- /dev/null +++ b/apps/runtime/lib/runtime.ex @@ -0,0 +1,18 @@ +defmodule Runtime do + @moduledoc """ + Documentation for `Runtime`. + """ + + @doc """ + Hello world. + + ## Examples + + iex> Runtime.hello() + :world + + """ + def hello do + :world + end +end diff --git a/apps/runtime/mix.exs b/apps/runtime/mix.exs new file mode 100644 index 0000000..e3dc343 --- /dev/null +++ b/apps/runtime/mix.exs @@ -0,0 +1,41 @@ +defmodule Runtime.MixProject do + use Mix.Project + + def project do + [ + app: :runtime, + version: "0.1.0", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.13", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + {:injectx, "~> 0.1"}, + {:flow, "~> 1.0"}, + {:protobuf, "~> 0.9.0", override: true}, + {:grpc, github: "elixir-grpc/grpc", override: true}, + {:cowlib, "~> 2.11", override: true}, + {:grpc_prometheus, "~> 0.1"}, + {:jason, "~> 1.2"}, + {:toml, "~> 0.6", override: true}, + {:prometheus, "~> 4.6"}, + {:prometheus_plugs, "~> 1.1"}, + {:telemetry, "~> 0.4.3"} + ] + end +end diff --git a/apps/runtime/test/runtime_test.exs b/apps/runtime/test/runtime_test.exs new file mode 100644 index 0000000..0a10dbb --- /dev/null +++ b/apps/runtime/test/runtime_test.exs @@ -0,0 +1,8 @@ +defmodule RuntimeTest do + use ExUnit.Case + doctest Runtime + + test "greets the world" do + assert Runtime.hello() == :world + end +end diff --git a/apps/runtime/test/test_helper.exs b/apps/runtime/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/apps/runtime/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/apps/runtime_grpc/.formatter.exs b/apps/runtime_grpc/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/apps/runtime_grpc/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/apps/runtime_grpc/.gitignore b/apps/runtime_grpc/.gitignore new file mode 100644 index 0000000..d5b30a5 --- /dev/null +++ b/apps/runtime_grpc/.gitignore @@ -0,0 +1,26 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +runtime_grpc-*.tar + +# Temporary files, for example, from tests. +/tmp/ diff --git a/apps/runtime_grpc/README.md b/apps/runtime_grpc/README.md new file mode 100644 index 0000000..b6e9d28 --- /dev/null +++ b/apps/runtime_grpc/README.md @@ -0,0 +1,21 @@ +# RuntimeGrpc + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `runtime_grpc` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:runtime_grpc, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at . + diff --git a/apps/runtime_grpc/lib/runtime_grpc.ex b/apps/runtime_grpc/lib/runtime_grpc.ex new file mode 100644 index 0000000..7d86f5a --- /dev/null +++ b/apps/runtime_grpc/lib/runtime_grpc.ex @@ -0,0 +1,18 @@ +defmodule RuntimeGrpc do + @moduledoc """ + Documentation for `RuntimeGrpc`. + """ + + @doc """ + Hello world. + + ## Examples + + iex> RuntimeGrpc.hello() + :world + + """ + def hello do + :world + end +end diff --git a/apps/runtime_grpc/mix.exs b/apps/runtime_grpc/mix.exs new file mode 100644 index 0000000..0676d6b --- /dev/null +++ b/apps/runtime_grpc/mix.exs @@ -0,0 +1,31 @@ +defmodule RuntimeGrpc.MixProject do + use Mix.Project + + def project do + [ + app: :runtime_grpc, + version: "0.1.0", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.13", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + {:runtime, in_umbrella: true} + ] + end +end diff --git a/apps/runtime_grpc/test/runtime_grpc_test.exs b/apps/runtime_grpc/test/runtime_grpc_test.exs new file mode 100644 index 0000000..d445b45 --- /dev/null +++ b/apps/runtime_grpc/test/runtime_grpc_test.exs @@ -0,0 +1,8 @@ +defmodule RuntimeGrpcTest do + use ExUnit.Case + doctest RuntimeGrpc + + test "greets the world" do + assert RuntimeGrpc.hello() == :world + end +end diff --git a/apps/runtime_grpc/test/test_helper.exs b/apps/runtime_grpc/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/apps/runtime_grpc/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/apps/runtime_wasm/.formatter.exs b/apps/runtime_wasm/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/apps/runtime_wasm/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/apps/runtime_wasm/.gitignore b/apps/runtime_wasm/.gitignore new file mode 100644 index 0000000..3de611c --- /dev/null +++ b/apps/runtime_wasm/.gitignore @@ -0,0 +1,26 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +runtime_wasm-*.tar + +# Temporary files, for example, from tests. +/tmp/ diff --git a/apps/runtime_wasm/README.md b/apps/runtime_wasm/README.md new file mode 100644 index 0000000..c9c9cb2 --- /dev/null +++ b/apps/runtime_wasm/README.md @@ -0,0 +1,21 @@ +# RuntimeWasm + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `runtime_wasm` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:runtime_wasm, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at . + diff --git a/apps/runtime_wasm/lib/runtime_wasm.ex b/apps/runtime_wasm/lib/runtime_wasm.ex new file mode 100644 index 0000000..e3a8ff8 --- /dev/null +++ b/apps/runtime_wasm/lib/runtime_wasm.ex @@ -0,0 +1,18 @@ +defmodule RuntimeWasm do + @moduledoc """ + Documentation for `RuntimeWasm`. + """ + + @doc """ + Hello world. + + ## Examples + + iex> RuntimeWasm.hello() + :world + + """ + def hello do + :world + end +end diff --git a/apps/runtime_wasm/mix.exs b/apps/runtime_wasm/mix.exs new file mode 100644 index 0000000..a4a6229 --- /dev/null +++ b/apps/runtime_wasm/mix.exs @@ -0,0 +1,33 @@ +defmodule RuntimeWasm.MixProject do + use Mix.Project + + def project do + [ + app: :runtime_wasm, + version: "0.1.0", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.13", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + {:runtime, in_umbrella: true}, + {:wasmex, "~> 0.5"}, + {:toml, "~> 0.6", override: true} + ] + end +end diff --git a/apps/runtime_wasm/test/runtime_wasm_test.exs b/apps/runtime_wasm/test/runtime_wasm_test.exs new file mode 100644 index 0000000..fcab4c8 --- /dev/null +++ b/apps/runtime_wasm/test/runtime_wasm_test.exs @@ -0,0 +1,8 @@ +defmodule RuntimeWasmTest do + use ExUnit.Case + doctest RuntimeWasm + + test "greets the world" do + assert RuntimeWasm.hello() == :world + end +end diff --git a/apps/runtime_wasm/test/test_helper.exs b/apps/runtime_wasm/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/apps/runtime_wasm/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/apps/store/.formatter.exs b/apps/store/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/apps/store/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/apps/store/.gitignore b/apps/store/.gitignore new file mode 100644 index 0000000..1201402 --- /dev/null +++ b/apps/store/.gitignore @@ -0,0 +1,26 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +store-*.tar + +# Temporary files, for example, from tests. +/tmp/ diff --git a/apps/store/README.md b/apps/store/README.md new file mode 100644 index 0000000..57f38f0 --- /dev/null +++ b/apps/store/README.md @@ -0,0 +1,21 @@ +# Store + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `store` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:store, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at . + diff --git a/apps/store/lib/store.ex b/apps/store/lib/store.ex new file mode 100644 index 0000000..bf82fbc --- /dev/null +++ b/apps/store/lib/store.ex @@ -0,0 +1,18 @@ +defmodule Store do + @moduledoc """ + Documentation for `Store`. + """ + + @doc """ + Hello world. + + ## Examples + + iex> Store.hello() + :world + + """ + def hello do + :world + end +end diff --git a/apps/store/mix.exs b/apps/store/mix.exs new file mode 100644 index 0000000..2968689 --- /dev/null +++ b/apps/store/mix.exs @@ -0,0 +1,33 @@ +defmodule Store.MixProject do + use Mix.Project + + def project do + [ + app: :store, + version: "0.1.0", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.13", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}, + # {:sibling_app_in_umbrella, in_umbrella: true} + ] + end +end diff --git a/apps/store/test/store_test.exs b/apps/store/test/store_test.exs new file mode 100644 index 0000000..86aa334 --- /dev/null +++ b/apps/store/test/store_test.exs @@ -0,0 +1,8 @@ +defmodule StoreTest do + use ExUnit.Case + doctest Store + + test "greets the world" do + assert Store.hello() == :world + end +end diff --git a/apps/store/test/test_helper.exs b/apps/store/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/apps/store/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/apps/store_inmemory/.formatter.exs b/apps/store_inmemory/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/apps/store_inmemory/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/apps/store_inmemory/.gitignore b/apps/store_inmemory/.gitignore new file mode 100644 index 0000000..388f86a --- /dev/null +++ b/apps/store_inmemory/.gitignore @@ -0,0 +1,26 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +store_inmemory-*.tar + +# Temporary files, for example, from tests. +/tmp/ diff --git a/apps/store_inmemory/README.md b/apps/store_inmemory/README.md new file mode 100644 index 0000000..f261ebc --- /dev/null +++ b/apps/store_inmemory/README.md @@ -0,0 +1,21 @@ +# StoreInmemory + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `store_inmemory` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:store_inmemory, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at . + diff --git a/apps/store_inmemory/lib/store_inmemory.ex b/apps/store_inmemory/lib/store_inmemory.ex new file mode 100644 index 0000000..ff102ca --- /dev/null +++ b/apps/store_inmemory/lib/store_inmemory.ex @@ -0,0 +1,18 @@ +defmodule StoreInmemory do + @moduledoc """ + Documentation for `StoreInmemory`. + """ + + @doc """ + Hello world. + + ## Examples + + iex> StoreInmemory.hello() + :world + + """ + def hello do + :world + end +end diff --git a/apps/store_inmemory/mix.exs b/apps/store_inmemory/mix.exs new file mode 100644 index 0000000..2c40ab2 --- /dev/null +++ b/apps/store_inmemory/mix.exs @@ -0,0 +1,33 @@ +defmodule StoreInmemory.MixProject do + use Mix.Project + + def project do + [ + app: :store_inmemory, + version: "0.1.0", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.13", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}, + # {:sibling_app_in_umbrella, in_umbrella: true} + ] + end +end diff --git a/apps/store_inmemory/test/store_inmemory_test.exs b/apps/store_inmemory/test/store_inmemory_test.exs new file mode 100644 index 0000000..a349ec1 --- /dev/null +++ b/apps/store_inmemory/test/store_inmemory_test.exs @@ -0,0 +1,8 @@ +defmodule StoreInmemoryTest do + use ExUnit.Case + doctest StoreInmemory + + test "greets the world" do + assert StoreInmemory.hello() == :world + end +end diff --git a/apps/store_inmemory/test/test_helper.exs b/apps/store_inmemory/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/apps/store_inmemory/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() From 2d185b945c2dfd46f8c7e7b9ad4763fe2d589b02 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Fri, 18 Feb 2022 20:48:23 -0300 Subject: [PATCH 14/19] Refactor. Part I --- apps/eventing/.formatter.exs | 4 + apps/eventing/.gitignore | 26 ++ apps/eventing/README.md | 21 ++ apps/eventing/lib/eventing.ex | 18 ++ apps/eventing/mix.exs | 33 +++ apps/eventing/test/eventing_test.exs | 8 + apps/eventing/test/test_helper.exs | 1 + .../massa_proxy/runtime/grpc/dispatcher.ex | 4 +- .../grpc/protocol/action/action_handler.ex | 23 +- .../runtime/grpc/protocol/action/protocol.ex | 4 +- .../grpc/protocol/action/stream_handler.ex | 6 +- .../grpc/protocol/discovery/manager.ex | 11 +- .../lib/massa_proxy/runtime/middleware.ex | 14 +- .../lib/massa_proxy/server/grpc_server.ex | 6 +- apps/massa_proxy/lib/massa_proxy/util.ex | 117 --------- apps/massa_proxy/lib/supervisor.ex | 2 - apps/massa_proxy/mix.exs | 4 +- .../lib}/entity/entity_registry.ex | 6 +- .../lib}/entity/entity_registry_supervisor.ex | 4 +- .../runtime/lib/protocol/command_processor.ex | 12 + apps/runtime/lib/protocol/handler.ex | 12 + apps/runtime/lib/protocol/middleware.ex | 246 ++++++++++++++++++ .../lib}/protocol/router.ex | 9 +- apps/runtime/lib/runtime.ex | 24 +- apps/runtime/lib/util.ex | 124 +++++++++ apps/runtime/mix.exs | 6 +- .../lib/protocol/action/action_middleware.ex | 72 +++++ .../lib/protocol/action/processor.ex | 42 +++ .../lib/protocol/action/protocol.ex | 101 +++++++ apps/runtime_grpc/lib/runtime_grpc.ex | 17 +- apps/runtime_grpc/mix.exs | 2 + apps/runtime_grpc/test/runtime_grpc_test.exs | 8 +- 32 files changed, 794 insertions(+), 193 deletions(-) create mode 100644 apps/eventing/.formatter.exs create mode 100644 apps/eventing/.gitignore create mode 100644 apps/eventing/README.md create mode 100644 apps/eventing/lib/eventing.ex create mode 100644 apps/eventing/mix.exs create mode 100644 apps/eventing/test/eventing_test.exs create mode 100644 apps/eventing/test/test_helper.exs rename apps/{massa_proxy/lib/massa_proxy/cluster => runtime/lib}/entity/entity_registry.ex (99%) rename apps/{massa_proxy/lib/massa_proxy/cluster => runtime/lib}/entity/entity_registry_supervisor.ex (73%) create mode 100644 apps/runtime/lib/protocol/command_processor.ex create mode 100644 apps/runtime/lib/protocol/handler.ex create mode 100644 apps/runtime/lib/protocol/middleware.ex rename apps/{massa_proxy/lib/massa_proxy => runtime/lib}/protocol/router.ex (94%) create mode 100644 apps/runtime/lib/util.ex create mode 100644 apps/runtime_grpc/lib/protocol/action/action_middleware.ex create mode 100644 apps/runtime_grpc/lib/protocol/action/processor.ex create mode 100644 apps/runtime_grpc/lib/protocol/action/protocol.ex diff --git a/apps/eventing/.formatter.exs b/apps/eventing/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/apps/eventing/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/apps/eventing/.gitignore b/apps/eventing/.gitignore new file mode 100644 index 0000000..7c1ff53 --- /dev/null +++ b/apps/eventing/.gitignore @@ -0,0 +1,26 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +eventing-*.tar + +# Temporary files, for example, from tests. +/tmp/ diff --git a/apps/eventing/README.md b/apps/eventing/README.md new file mode 100644 index 0000000..dcc6f81 --- /dev/null +++ b/apps/eventing/README.md @@ -0,0 +1,21 @@ +# Eventing + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `eventing` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:eventing, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at . + diff --git a/apps/eventing/lib/eventing.ex b/apps/eventing/lib/eventing.ex new file mode 100644 index 0000000..2f2307d --- /dev/null +++ b/apps/eventing/lib/eventing.ex @@ -0,0 +1,18 @@ +defmodule Eventing do + @moduledoc """ + Documentation for `Eventing`. + """ + + @doc """ + Hello world. + + ## Examples + + iex> Eventing.hello() + :world + + """ + def hello do + :world + end +end diff --git a/apps/eventing/mix.exs b/apps/eventing/mix.exs new file mode 100644 index 0000000..422b7bc --- /dev/null +++ b/apps/eventing/mix.exs @@ -0,0 +1,33 @@ +defmodule Eventing.MixProject do + use Mix.Project + + def project do + [ + app: :eventing, + version: "0.1.0", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.13", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}, + # {:sibling_app_in_umbrella, in_umbrella: true} + ] + end +end diff --git a/apps/eventing/test/eventing_test.exs b/apps/eventing/test/eventing_test.exs new file mode 100644 index 0000000..d8cf404 --- /dev/null +++ b/apps/eventing/test/eventing_test.exs @@ -0,0 +1,8 @@ +defmodule EventingTest do + use ExUnit.Case + doctest Eventing + + test "greets the world" do + assert Eventing.hello() == :world + end +end diff --git a/apps/eventing/test/test_helper.exs b/apps/eventing/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/apps/eventing/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/dispatcher.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/dispatcher.ex index 0616e76..750ef81 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/dispatcher.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/dispatcher.ex @@ -23,7 +23,9 @@ defmodule MassaProxy.Runtime.Grpc.Server.Dispatcher do "Handle stream: #{inspect(stream)}. With persistence id: #{inspect(persistence_id)}" ) - with {:ok, _pid} <- MiddlewareSupervisor.start_middleware(payload) do + with {:ok, pid} <- MiddlewareSupervisor.start_middleware(payload) do + Logger.debug("Started middleware with pid: #{inspect(pid)}") + case entity_type do "cloudstate.action.ActionProtocol" -> ActionHandler.handle(payload) "cloudstate.eventsourced.EventSourced" -> EventSourcedHandler.handle(payload) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/action_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/action_handler.ex index ad86385..d62ac71 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/action_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/action_handler.ex @@ -5,20 +5,21 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Handler do so it is necessary to identify in the payload the type of request that is arriving to decide how to forward messages via the protocol to the user's function """ - require Logger - alias MassaProxy.Runtime.Grpc.Protocol.Action.Unary.Handler, as: UnaryHandler alias MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler, as: StreamHandler @behaviour MassaProxy.Protocol.Handler - @impl true - def handle(%{request_type: request_type} = payload) do - case request_type do - "unary" -> UnaryHandler.handle_unary(payload) - "stream_in" -> StreamHandler.handle_stream_in(payload) - "stream_out" -> StreamHandler.handle_stream_out(payload) - "streamed" -> StreamHandler.handle_streamed(payload) - end - end + @impl MassaProxy.Protocol.Handler + def handle(%{request_type: "unary"} = payload), + do: UnaryHandler.handle_unary(payload) + + def handle(%{request_type: "stream_in"} = payload), + do: StreamHandler.handle_stream_in(payload) + + def handle(%{request_type: "stream_out"} = payload), + do: StreamHandler.handle_stream_out(payload) + + def handle(%{request_type: "streamed"} = payload), + do: StreamHandler.handle_streamed(payload) end diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex index 491e9cf..ad23139 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/protocol.ex @@ -1,9 +1,9 @@ -defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Protocol do +defmodule Runtime.GRPC.Protocol.Action.Protocol do require Logger alias Cloudstate.{Action.ActionCommand, Action.ActionResponse, Metadata} alias Google.Protobuf.Any - alias MassaProxy.Util + alias Runtime.Util @type t :: map() @type command_type :: :payload | :metadata | :full diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex index 7a4068e..af54a50 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/action/stream_handler.ex @@ -9,7 +9,7 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler do alias MassaProxy.Runtime.Grpc.Protocol.Action.Protocol, as: ActionProtocol alias MassaProxy.Runtime.Middleware - import MassaProxy.Util, only: [get_connection: 0] + alias Runtime.Util def handle_streamed(%{stream: stream} = ctx) do with messages <- ActionProtocol.build_stream(ctx), @@ -37,7 +37,7 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler do def handle_stream_in(ctx) do messages = ActionProtocol.build_stream(ctx) - with {:ok, conn} <- get_connection(), + with {:ok, conn} <- Util.get_connection(), client_stream = ActionClient.handle_streamed_in(conn), task_result <- run_stream(client_stream, messages), :ok <- accumlate_stream_result(task_result), @@ -51,7 +51,7 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Action.Stream.Handler do def handle_stream_out(%{stream: stream} = ctx) do message = ActionProtocol.build_msg(ctx, :full) - with {:ok, conn} <- get_connection(), + with {:ok, conn} <- Util.get_connection(), {:ok, client_stream} <- ActionClient.handle_streamed_out(conn, message, []) do Stream.each(client_stream, fn {:ok, response} -> GRPC.Server.send_reply(stream, ActionProtocol.decode(ctx, response)) diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/discovery/manager.ex b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/discovery/manager.ex index 1f2d9f7..958cb99 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/discovery/manager.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/grpc/protocol/discovery/manager.ex @@ -8,6 +8,7 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Discovery.Manager do alias MassaProxy.CloudstateEntity alias MassaProxy.Server.GrpcServer alias Google.Protobuf.FileDescriptorSet + alias Runtime.{Entity.EntityRegistry, Util} inject(MassaProxy.Infra.Config) @@ -81,10 +82,10 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Discovery.Manager do case entity.entity_type do "cloudstate.eventsourced.EventSourced" -> - MassaProxy.Entity.EntityRegistry.register("EventSourced", [entity]) + EntityRegistry.register("EventSourced", [entity]) "cloudstate.action.ActionProtocol" -> - MassaProxy.Entity.EntityRegistry.register("Action", [entity]) + EntityRegistry.register("Action", [entity]) _ -> Logger.warn("Unknown Entity #{entity.entity_type}") @@ -173,7 +174,7 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Discovery.Manager do defp extract_field_attributes(field) do has_key = if field.options != nil do - opts = MassaProxy.Util.contains_key?(field) + opts = Util.contains_key?(field) Logger.debug("Has key?: #{inspect(opts)}") end @@ -195,7 +196,7 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Discovery.Manager do defp extract_service_method(method) do http_options = if method.options != nil do - http_rules = MassaProxy.Util.get_http_rule(method) + http_rules = Util.get_http_rule(method) Logger.debug("MehodOptions: #{inspect(http_rules)}") %{type: "http", data: http_rules} @@ -203,7 +204,7 @@ defmodule MassaProxy.Runtime.Grpc.Protocol.Discovery.Manager do eventing_options = if method.options != nil do - evt_rules = MassaProxy.Util.get_eventing_rule(method) + evt_rules = Util.get_eventing_rule(method) Logger.debug("MehodOptions: #{inspect(evt_rules)}") %{type: "eventing", data: evt_rules} diff --git a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex index 0683136..9a19ae2 100644 --- a/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex +++ b/apps/massa_proxy/lib/massa_proxy/runtime/middleware.ex @@ -8,10 +8,10 @@ defmodule MassaProxy.Runtime.Middleware do alias Cloudstate.{Action.ActionResponse, SideEffect} alias Cloudstate.Action.ActionProtocol.Stub, as: ActionClient - alias MassaProxy.Protocol.Router + alias Runtime.Protocol.Router alias MassaProxy.Runtime.Grpc.Protocol.Action.Protocol, as: ActionProtocol - import MassaProxy.Util, only: [get_connection: 0] + alias Runtime.Util @impl true def init(state) do @@ -30,10 +30,10 @@ defmodule MassaProxy.Runtime.Middleware do state ) do result = - with {:ok, channel} <- get_connection(), - {:ok, %ActionResponse{side_effects: effects} = commands} <- + with {:ok, channel} <- Util.get_connection(), + {:ok, %ActionResponse{side_effects: effects} = command} <- ActionClient.handle_unary(channel, message), - {:ok, result} <- process_command(nil, context, commands) do + {:ok, result} <- process_command(nil, context, command) do call_effects(context, effects) {:ok, result} else @@ -53,7 +53,7 @@ defmodule MassaProxy.Runtime.Middleware do ) do spawn(fn -> stream_result = - with {:ok, conn} <- get_connection(), + with {:ok, conn} <- Util.get_connection(), client_stream = ActionClient.handle_streamed(conn), :ok <- run_stream(client_stream, messages) |> Stream.run(), {:ok, consumer_stream} <- GRPC.Stub.recv(client_stream) do @@ -98,7 +98,7 @@ defmodule MassaProxy.Runtime.Middleware do @impl true def handle_cast({:handle_effect, ctx}, state) do with message <- ActionProtocol.build_msg(ctx), - {:ok, channel} <- get_connection(), + {:ok, channel} <- Util.get_connection(), {:ok, %ActionResponse{} = commands} <- ActionClient.handle_unary(channel, message), {:ok, result} <- process_command(nil, ctx, commands) do diff --git a/apps/massa_proxy/lib/massa_proxy/server/grpc_server.ex b/apps/massa_proxy/lib/massa_proxy/server/grpc_server.ex index 4f80b02..db33485 100644 --- a/apps/massa_proxy/lib/massa_proxy/server/grpc_server.ex +++ b/apps/massa_proxy/lib/massa_proxy/server/grpc_server.ex @@ -4,6 +4,7 @@ defmodule MassaProxy.Server.GrpcServer do alias MassaProxy.{Util, Infra.Cache, Server.HttpRouter} alias MassaProxy.Infra.Cache.Distributed + alias Runtime.Util def start(descriptors, entities) do case Cache.get(:cached_servers, :grpc) do @@ -170,7 +171,10 @@ defmodule MassaProxy.Server.GrpcServer do entities |> Flow.from_enumerable() |> Flow.map( - &Enum.join([Util.normalize_service_name(&1.service_name), "Service.ProxyService"], ".") + &Enum.join( + [Util.normalize_service_name(&1.service_name), "Service.ProxyService"], + "." + ) ) |> Enum.to_list() diff --git a/apps/massa_proxy/lib/massa_proxy/util.ex b/apps/massa_proxy/lib/massa_proxy/util.ex index f818bf6..a0c7656 100644 --- a/apps/massa_proxy/lib/massa_proxy/util.ex +++ b/apps/massa_proxy/lib/massa_proxy/util.ex @@ -79,123 +79,6 @@ defmodule MassaProxy.Util do end end - def contains_key?(field_descriptor) do - Logger.debug("FieldOptions: #{inspect(field_descriptor)}") - - entity_key_ext = - Google.Protobuf.FieldOptions.get_extension( - field_descriptor.options, - Cloudstate.PbExtension, - :entity_key - ) - - Logger.debug("Entity key extension: #{inspect(entity_key_ext)}") - entity_key_ext - end - - def get_http_rule(method_descriptor) do - Logger.debug("MethodOptions HTTP Rules: #{inspect(method_descriptor)}") - - Google.Protobuf.MethodOptions.get_extension( - method_descriptor.options, - Google.Api.PbExtension, - :http - ) - end - - def get_eventing_rule(method_descriptor) do - Logger.debug("MethodOptions Eventing Rules: #{inspect(method_descriptor)}") - - evt_ext = - Google.Protobuf.MethodOptions.get_extension( - method_descriptor.options, - Cloudstate.PbExtension, - :eventing - ) - - Logger.debug("Eventing extension: #{inspect(evt_ext)}") - evt_ext - end - - def get_type(method) do - type = - cond do - method.unary == true -> "unary" - method.streamed == true -> "streamed" - method.stream_in == true -> "stream_in" - method.stream_out == true -> "stream_out" - end - - type - end - - def get_type_url(type) when is_binary(type) do - if String.contains?(type, "type.googleapis.com/") do - type - else - raise "Invalid type: #{type}" - end - end - - def get_type_url(type) when is_atom(type) do - parts = - type - |> to_string - |> String.replace("Elixir.", "") - |> String.split(".") - - package_name = - with {_, list} <- parts |> List.pop_at(-1), - do: list |> Stream.map(&String.downcase(&1)) |> Enum.join(".") - - type_name = parts |> List.last() - "type.googleapis.com/#{package_name}.#{type_name}" - end - - def compile(file) do - Code.compile_string(file) - rescue - error in UndefinedFunctionError -> - Logger.error("Error in Module definition. Make sure the service name is correct") - raise error - - error -> - Logger.error("Error during Service compilation phase #{inspect(error)}") - end - - def normalize_service_name(name) do - name - |> String.split(".") - |> Stream.map(&Macro.camelize(&1)) - |> Enum.join(".") - end - - def normalize_method_name(name), do: Macro.underscore(name) - - def get_module(filename, bindings \\ []), do: EEx.eval_file(filename, bindings) - - def get_connection(), - do: - GRPC.Stub.connect(get_address(is_uds_enable?()), - interceptors: [GRPC.Logger.Client], - adapter_opts: %{http2_opts: %{keepalive: 10000}} - ) - - def get_uds_address(), - do: Application.get_env(:massa_proxy, :user_function_sock_addr, "/var/run/cloudstate.sock") - - def is_uds_enable?(), - do: Application.get_env(:massa_proxy, :user_function_uds_enable, false) - - defp get_function_host(), - do: Application.get_env(:massa_proxy, :user_function_host, "127.0.0.1") - - def get_function_port(), do: Application.get_env(:massa_proxy, :user_function_port, 8080) - - def get_address(false), do: "#{get_function_host()}:#{get_function_port()}" - - def get_address(true), do: "#{get_uds_address()}" - defp get_gossip_strategy(), do: [ proxy: [ diff --git a/apps/massa_proxy/lib/supervisor.ex b/apps/massa_proxy/lib/supervisor.ex index ac59ba6..fa46833 100644 --- a/apps/massa_proxy/lib/supervisor.ex +++ b/apps/massa_proxy/lib/supervisor.ex @@ -12,14 +12,12 @@ defmodule MassaProxy.Children do def init(config) do children = [ http_server(config), - {Task.Supervisor, name: MassaProxy.TaskSupervisor}, {Registry, [name: MassaProxy.LocalRegistry, keys: :unique]}, {DynamicSupervisor, [name: MassaProxy.LocalSupervisor, strategy: :one_for_one]}, {DynamicSupervisor, [name: MassaProxy.Runtime.MiddlewareSupervisor, strategy: :one_for_one]}, {MassaProxy.Infra.Cache.Distributed, []}, local_node(), - {MassaProxy.Entity.EntityRegistry.Supervisor, [%{}]}, %{ id: CachedServers, start: {MassaProxy.Infra.Cache, :start_link, [[cache_name: :cached_servers]]} diff --git a/apps/massa_proxy/mix.exs b/apps/massa_proxy/mix.exs index d32bbf1..4f3d811 100644 --- a/apps/massa_proxy/mix.exs +++ b/apps/massa_proxy/mix.exs @@ -21,7 +21,8 @@ defmodule MassaProxy.MixProject do [ extra_applications: [ :logger, - :observer + :observer, + :runtime ], mod: {MassaProxy, []} ] @@ -44,7 +45,6 @@ defmodule MassaProxy.MixProject do # Cluster deps {:libcluster, "~> 3.3"}, {:horde, "~> 0.8"}, - {:phoenix_pubsub, "~> 2.0"}, {:nebulex, "~> 2.1"}, {:ranch, "~> 1.8"}, diff --git a/apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry.ex b/apps/runtime/lib/entity/entity_registry.ex similarity index 99% rename from apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry.ex rename to apps/runtime/lib/entity/entity_registry.ex index 1f9a0db..37c04d4 100644 --- a/apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry.ex +++ b/apps/runtime/lib/entity/entity_registry.ex @@ -1,4 +1,4 @@ -defmodule MassaProxy.Entity.EntityRegistry do +defmodule Runtime.Entity.EntityRegistry do @moduledoc false use GenServer require Logger @@ -66,8 +66,6 @@ defmodule MassaProxy.Entity.EntityRegistry do {:noreply, new_state} end - defp get_simple_name(service_name), do: String.split(service_name, ".") |> List.last() - @impl true def handle_call({:get, entity_type, service_name, method_name}, _from, state) do nodes = @@ -198,4 +196,6 @@ defmodule MassaProxy.Entity.EntityRegistry do end defp include_entities(state, message), do: Map.merge(state, message) + + defp get_simple_name(service_name), do: String.split(service_name, ".") |> List.last() end diff --git a/apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry_supervisor.ex b/apps/runtime/lib/entity/entity_registry_supervisor.ex similarity index 73% rename from apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry_supervisor.ex rename to apps/runtime/lib/entity/entity_registry_supervisor.ex index bd90c96..cc91ee3 100644 --- a/apps/massa_proxy/lib/massa_proxy/cluster/entity/entity_registry_supervisor.ex +++ b/apps/runtime/lib/entity/entity_registry_supervisor.ex @@ -1,4 +1,4 @@ -defmodule MassaProxy.Entity.EntityRegistry.Supervisor do +defmodule Runtime.Entity.EntityRegistry.Supervisor do @moduledoc false use Supervisor @@ -10,7 +10,7 @@ defmodule MassaProxy.Entity.EntityRegistry.Supervisor do def init(_args) do children = [ {Phoenix.PubSub, name: :entity_channel}, - MassaProxy.Entity.EntityRegistry.child_spec(%{}) + Runtime.Entity.EntityRegistry.child_spec(%{}) ] Supervisor.init(children, strategy: :one_for_one) diff --git a/apps/runtime/lib/protocol/command_processor.ex b/apps/runtime/lib/protocol/command_processor.ex new file mode 100644 index 0000000..b0946f3 --- /dev/null +++ b/apps/runtime/lib/protocol/command_processor.ex @@ -0,0 +1,12 @@ +defmodule Runtime.Protocol.CommandProcessor do + @moduledoc """ + CommandProcessor executes arbitrary logic on a command. + """ + + @type context :: any() + @type command :: any() + @type result :: any() + @type error :: any() + + @callback apply(context, command) :: {:ok, result} | {:error, error} +end diff --git a/apps/runtime/lib/protocol/handler.ex b/apps/runtime/lib/protocol/handler.ex new file mode 100644 index 0000000..4dcf2f1 --- /dev/null +++ b/apps/runtime/lib/protocol/handler.ex @@ -0,0 +1,12 @@ +defmodule Runtime.Protocol.Handler do + @moduledoc """ + This Behavior must be implemented by each entity protocol to handle + requests. + + Requests will be forwarded without the expectation of a return to the dispatcher + because the stream will be forwarded to the implementation of this Behavior, + leaving it to the handling and forwarding of an appropriate response to the caller + """ + + @callback handle(payload :: term) :: {:ok} | {:error, reason :: term} +end diff --git a/apps/runtime/lib/protocol/middleware.ex b/apps/runtime/lib/protocol/middleware.ex new file mode 100644 index 0000000..8bfa3f0 --- /dev/null +++ b/apps/runtime/lib/protocol/middleware.ex @@ -0,0 +1,246 @@ +defmodule Runtime.Protocol.Middleware do + @doc """ + Middleware is a bridge between the protocol and the user function. + The main purpose of middleware is to provide a way to add some abstraction between + the underlying transport, user function and the Entity processor. + + The main responsibility of this module's callbacks is to abstract the transport, that is, + the communication channel with the user role. + Processing rules should not be performed by the implementations of this module's callbacks. + """ + @type state :: any() + @type reason :: any() + + @callback do_init(state) :: + {:ok, state} + | {:ok, state, timeout() | :hibernate | {:continue, term()}} + | :ignore + | {:stop, reason :: any()} + + @callback handle_effect(any()) :: {:ok, any()} | {:error, any()} + + @callback handle_forward(any(), any()) :: {:ok, any()} | {:error, any()} + + @callback handle_unary(any(), any()) :: {:ok, any()} | {:error, any()} + + @callback handle_streamed(any(), any()) :: {:ok, Stream.t()} | {:error, any()} + + @callback handle_stream_in(any(), Stream.t()) :: {:ok, any()} | {:error, any()} + + @callback handle_stream_out(any(), any()) :: {:ok, Stream.t()} | {:error, any()} + + def do_init(state), do: {:ok, state} + + def handle_effect(_context) do + raise "Not implemented" + end + + def handle_forward(_context, _message) do + raise "Not implemented" + end + + def handle_unary(_context, _message) do + raise "Not implemented" + end + + def handle_streamed(_context, _messages) do + raise "Not implemented" + end + + def handle_stream_in(_context, _messages) do + raise "Not implemented" + end + + def handle_stream_out(_context, _message) do + raise "Not implemented" + end + + defoverridable do_init: 1, + handle_effect: 1, + handle_forward: 2, + handle_unary: 2, + handle_streamed: 2, + handle_stream_in: 2, + handle_stream_out: 2 + + defmacro __using__(opts) do + quote bind_quoted: [opts: opts] do + @behaviour Runtime.Protocol.Middleware + use GenServer + + require Logger + + alias Cloudstate.{Action.ActionResponse, SideEffect} + alias Cloudstate.Action.ActionProtocol.Stub, as: ActionClient + alias Runtime.Protocol.Router + alias MassaProxy.Runtime.Grpc.Protocol.Action.Protocol, as: ActionProtocol + + alias Runtime + + @command_processor opts[:command_processor] + + def start_link(%{name: name} = state) do + GenServer.start_link(__MODULE__, state, name: name) + end + + @impl true + def init(state) do + {:ok, state} + end + + @impl true + def handle_call( + {:handle_unary, %{context: context, payload: message} = _input}, + _from, + state + ) do + result = + with {:ok, %{side_effects: effects} = command} <- handle_unary(context, message), + {:ok, result} <- @command_processor.apply(context, command) do + call_effects(context, effects) + {:ok, result} + else + {:error, reason} -> {:error, "Failure to make unary request #{inspect(reason)}"} + end + + Logger.debug("Middleware User function response #{inspect(result)}") + + {:reply, result, state} + end + + @impl true + def handle_call( + {:handle_streamed, %{context: context, payload: messages} = _input}, + from, + state + ) do + spawn(fn -> + stream_result = + with {:ok, consumer_stream} <- handle_streamed(context, messages) do + consumer_stream = + consumer_stream + |> Stream.map(fn + {:ok, %{side_effects: effects} = command} -> + Logger.debug("Consumer Stream result: #{inspect(command)}") + + result = + case @command_processor.apply(context, command) do + {:ok, result} -> + {:ok, result} + + {:error, reason} -> + {:error, "Failure on process command #{inspect(reason)}"} + end + + call_effects(context, effects) + result + + {:error, reason} -> + {:error, "Failure on process client stream #{inspect(reason)}"} + end) + |> Enum.to_list() + + {:ok, consumer_stream} + else + {:ok, []} -> + {:error, "Client not returned a stream"} + + {:error, reason} -> + {:error, reason} + end + + GenServer.reply(from, stream_result) + end) + + {:noreply, state} + end + + @impl true + def handle_cast({:handle_effect, context}, state) do + with {:ok, %{side_effects: effects} = command} <- handle_effect(context), + {:ok, result} <- @command_processor.apply(context, command) do + Logger.debug( + "Handle effects User function response #{inspect(command)}. With commands result #{inspect(result)}" + ) + + call_effects(context, effects) + else + {:error, reason} -> + Logger.warn("Failure to make unary request #{inspect(reason)}") + end + + {:noreply, state} + end + + defp call_effects(_ctx, []), do: {:ok, []} + + defp call_effects( + %{entity_type: entity_type} = _ctx, + effects + ) + when is_list(effects) and length(effects) > 0 do + Enum.each(effects, fn %SideEffect{ + service_name: service_name, + command_name: command_name, + synchronous: synchronous, + payload: %Google.Protobuf.Any{type_url: input_type} = payload + } = effect -> + Logger.debug( + "Handling side effect #{inspect(effect)}} with command name: #{command_name} and input type: #{input_type}" + ) + + message = %{ + message: payload, + entity_type: nil, + service_name: nil, + request_type: nil, + original_method: nil, + input_type: nil, + output_type: nil, + persistence_id: nil, + stream: nil + } + + Router.route( + entity_type, + service_name, + command_name, + input_type, + !synchronous, + __MODULE__, + :effect, + message + ) + end) + end + + defp call_effects(_ctx, _), do: {:ok, []} + + # end quoted + end + + # end defmacro + end + + # Client API + def unary(%{entity_type: entity_type} = ctx, message) do + GenServer.call(get_name(entity_type), {:handle_unary, %{context: ctx, payload: message}}) + end + + def streamed(%{entity_type: entity_type} = ctx, messages) do + GenServer.call(get_name(entity_type), {:handle_streamed, %{context: ctx, payload: messages}}) + end + + def effect(%{entity_type: entity_type} = ctx) do + GenServer.cast(get_name(entity_type), {:handle_effect, ctx}) + end + + defp get_name(entity_type) do + mod = + entity_type + |> String.split(".") + |> Enum.at(-1) + + Module.concat(__MODULE__, mod) + end +end diff --git a/apps/massa_proxy/lib/massa_proxy/protocol/router.ex b/apps/runtime/lib/protocol/router.ex similarity index 94% rename from apps/massa_proxy/lib/massa_proxy/protocol/router.ex rename to apps/runtime/lib/protocol/router.ex index 9955f82..32c940a 100644 --- a/apps/massa_proxy/lib/massa_proxy/protocol/router.ex +++ b/apps/runtime/lib/protocol/router.ex @@ -1,13 +1,12 @@ -defmodule MassaProxy.Protocol.Router do +defmodule Runtime.Protocol.Router do @doc """ Dispatch the given `mod`, `fun`, `args` request to the appropriate node based on the `bucket`. """ require Logger - alias MassaProxy.Entity.EntityRegistry - alias MassaProxy.TaskSupervisor - alias MassaProxy.Util + alias ProxyRuntime.TaskSupervisor + alias Runtime.{Entity.EntityRegistry, Util} @timeout 10000 @@ -21,6 +20,8 @@ defmodule MassaProxy.Protocol.Router do fun, %{message: payload} = message ) do + Logger.debug("Routing #{mod}:#{fun}") + with node_entities <- EntityRegistry.lookup(entity_type, service_name, command_name) do targets = Enum.map(node_entities, fn %{node: member, entity: entity} = _node_entity -> diff --git a/apps/runtime/lib/runtime.ex b/apps/runtime/lib/runtime.ex index cfc98fb..393463f 100644 --- a/apps/runtime/lib/runtime.ex +++ b/apps/runtime/lib/runtime.ex @@ -1,18 +1,20 @@ defmodule Runtime do @moduledoc """ - Documentation for `Runtime`. + `Runtime`. """ + use Application - @doc """ - Hello world. + @impl true + def start(_type, _args) do + children = + [ + {Task.Supervisor, name: ProxyRuntime.TaskSupervisor}, + {Runtime.Entity.EntityRegistry.Supervisor, [%{}]} + ] + |> Stream.reject(&is_nil/1) + |> Enum.to_list() - ## Examples - - iex> Runtime.hello() - :world - - """ - def hello do - :world + opts = [strategy: :one_for_one, name: ProxyRuntime.Supervisor] + Supervisor.start_link(children, opts) end end diff --git a/apps/runtime/lib/util.ex b/apps/runtime/lib/util.ex new file mode 100644 index 0000000..7cc2260 --- /dev/null +++ b/apps/runtime/lib/util.ex @@ -0,0 +1,124 @@ +defmodule Runtime.Util do + @moduledoc false + require Logger + + def contains_key?(field_descriptor) do + Logger.debug("FieldOptions: #{inspect(field_descriptor)}") + + entity_key_ext = + Google.Protobuf.FieldOptions.get_extension( + field_descriptor.options, + Cloudstate.PbExtension, + :entity_key + ) + + Logger.debug("Entity key extension: #{inspect(entity_key_ext)}") + entity_key_ext + end + + def get_http_rule(method_descriptor) do + Logger.debug("MethodOptions HTTP Rules: #{inspect(method_descriptor)}") + + Google.Protobuf.MethodOptions.get_extension( + method_descriptor.options, + Google.Api.PbExtension, + :http + ) + end + + def get_eventing_rule(method_descriptor) do + Logger.debug("MethodOptions Eventing Rules: #{inspect(method_descriptor)}") + + evt_ext = + Google.Protobuf.MethodOptions.get_extension( + method_descriptor.options, + Cloudstate.PbExtension, + :eventing + ) + + Logger.debug("Eventing extension: #{inspect(evt_ext)}") + evt_ext + end + + def get_type(method) do + type = + cond do + method.unary == true -> "unary" + method.streamed == true -> "streamed" + method.stream_in == true -> "stream_in" + method.stream_out == true -> "stream_out" + end + + type + end + + def get_type_url(type) when is_binary(type) do + if String.contains?(type, "type.googleapis.com/") do + type + else + raise "Invalid type: #{type}" + end + end + + def get_type_url(type) when is_atom(type) do + parts = + type + |> to_string + |> String.replace("Elixir.", "") + |> String.split(".") + + package_name = + with {_, list} <- parts |> List.pop_at(-1), + do: list |> Stream.map(&String.downcase(&1)) |> Enum.join(".") + + type_name = parts |> List.last() + "type.googleapis.com/#{package_name}.#{type_name}" + end + + def compile(file) do + Code.compile_string(file) + rescue + error in UndefinedFunctionError -> + Logger.error("Error in Module definition. Make sure the service name is correct") + raise error + + error -> + Logger.error("Error during Service compilation phase #{inspect(error)}") + end + + def normalize_service_name(name) do + name + |> String.split(".") + |> Stream.map(&Macro.camelize(&1)) + |> Enum.join(".") + end + + def normalize_method_name(name), do: Macro.underscore(name) + + def get_module(filename, bindings \\ []), do: EEx.eval_file(filename, bindings) + + @doc """ + Get client gRPC connection when Runtime is a gRPC runtime. + """ + def get_connection(), + do: + GRPC.Stub.connect(get_address(is_uds_enable?()), + interceptors: [GRPC.Logger.Client], + adapter_opts: %{http2_opts: %{keepalive: 10000}} + ) + + def get_uds_address(), + do: Application.get_env(:massa_proxy, :user_function_sock_addr, "/var/run/cloudstate.sock") + + def is_uds_enable?(), + do: Application.get_env(:massa_proxy, :user_function_uds_enable, false) + + defp get_function_host(), + do: Application.get_env(:massa_proxy, :user_function_host, "127.0.0.1") + + def get_function_port(), do: Application.get_env(:massa_proxy, :user_function_port, 8080) + + def get_address(false), do: "#{get_function_host()}:#{get_function_port()}" + + def get_address(true), do: "#{get_uds_address()}" +end diff --git a/apps/runtime/mix.exs b/apps/runtime/mix.exs index e3dc343..0968cda 100644 --- a/apps/runtime/mix.exs +++ b/apps/runtime/mix.exs @@ -18,6 +18,7 @@ defmodule Runtime.MixProject do # Run "mix help compile.app" to learn about applications. def application do [ + mod: {Runtime, []}, extra_applications: [:logger] ] end @@ -25,6 +26,8 @@ defmodule Runtime.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ + {:cloudstate_protocol, in_umbrella: true}, + {:eigr_protocol, in_umbrella: true}, {:injectx, "~> 0.1"}, {:flow, "~> 1.0"}, {:protobuf, "~> 0.9.0", override: true}, @@ -35,7 +38,8 @@ defmodule Runtime.MixProject do {:toml, "~> 0.6", override: true}, {:prometheus, "~> 4.6"}, {:prometheus_plugs, "~> 1.1"}, - {:telemetry, "~> 0.4.3"} + {:telemetry, "~> 0.4.3"}, + {:phoenix_pubsub, "~> 2.0"} ] end end diff --git a/apps/runtime_grpc/lib/protocol/action/action_middleware.ex b/apps/runtime_grpc/lib/protocol/action/action_middleware.ex new file mode 100644 index 0000000..db24791 --- /dev/null +++ b/apps/runtime_grpc/lib/protocol/action/action_middleware.ex @@ -0,0 +1,72 @@ +defmodule Runtime.GRPC.Protocol.Action.Middleware do + use Runtime.Protocol.Middleware, command_processor: Runtime.Protocol.Action.Processor + + alias Cloudstate.Action.ActionProtocol.Stub, as: ActionClient + alias Runtime.GRPC.Protocol.Action.Protocol, as: ActionProtocol + alias Runtime.Util + + @impl true + def do_init(state), do: {:ok, state} + + @impl true + def handle_effect(context) do + with message <- ActionProtocol.build_msg(context), + {:ok, channel} <- Util.get_connection(), + {:ok, commands} <- ActionClient.handle_unary(channel, message) do + {:ok, commands} + else + {:error, reason} -> + {:error, {:error, "Failure to make side effect request #{inspect(reason)}"}} + end + end + + @impl true + def handle_forward(_context, _message) do + raise "Not implemented" + end + + @impl true + def handle_unary(_context, message) do + with {:ok, channel} <- Util.get_connection(), + {:ok, command} <- ActionClient.handle_unary(channel, message) do + {:ok, command} + else + {:error, reason} -> {:error, "Failure to make unary request #{inspect(reason)}"} + end + end + + @impl true + def handle_streamed(_context, messages) do + with {:ok, channel} <- Util.get_connection(), + client_stream = ActionClient.handle_streamed(channel), + :ok <- run_stream(client_stream, messages) |> Stream.run(), + {:ok, consumer_stream} <- GRPC.Stub.recv(client_stream) do + {:ok, Enum.to_list(consumer_stream)} + else + {:error, reason} -> {:error, "Failure to make streamed request #{inspect(reason)}"} + end + end + + @impl true + def handle_stream_in(_context, _messages) do + raise "Not implemented" + end + + @impl true + def handle_stream_out(_context, _message) do + raise "Not implemented" + end + + defp run_stream(client_stream, messages) do + messages + |> Stream.map(&send_stream_msg(client_stream, &1)) + end + + defp send_stream_msg(client_stream, :halt) do + GRPC.Stub.end_stream(client_stream) + end + + defp send_stream_msg(client_stream, msg) do + GRPC.Stub.send_request(client_stream, msg, []) + end +end diff --git a/apps/runtime_grpc/lib/protocol/action/processor.ex b/apps/runtime_grpc/lib/protocol/action/processor.ex new file mode 100644 index 0000000..4af64a3 --- /dev/null +++ b/apps/runtime_grpc/lib/protocol/action/processor.ex @@ -0,0 +1,42 @@ +defmodule Runtime.GRPC.Protocol.Action.Processor do + @moduledoc """ + This module defines the command processor for actions. + """ + require Logger + + alias Cloudstate.Action.ActionResponse + + @behaviour Runtime.Protocol.CommandProcessor + + def apply( + _context, + %ActionResponse{response: {:reply, %Cloudstate.Reply{} = _reply}} = message + ) do + {:ok, message} + end + + def apply( + _context, + %ActionResponse{response: {:failure, %Cloudstate.Failure{} = _failure}} = message + ) do + {:ok, message} + end + + def apply( + _context, + %ActionResponse{response: {:forward, %Cloudstate.Forward{} = _forward}} = message + ) do + {:ok, message} + end + + def apply( + _context, + %ActionResponse{response: nil} = _message + ) do + {:ok, %ActionResponse{}} + end + + def apply(nil, _context, message) do + {:ok, message} + end +end diff --git a/apps/runtime_grpc/lib/protocol/action/protocol.ex b/apps/runtime_grpc/lib/protocol/action/protocol.ex new file mode 100644 index 0000000..ad23139 --- /dev/null +++ b/apps/runtime_grpc/lib/protocol/action/protocol.ex @@ -0,0 +1,101 @@ +defmodule Runtime.GRPC.Protocol.Action.Protocol do + require Logger + + alias Cloudstate.{Action.ActionCommand, Action.ActionResponse, Metadata} + alias Google.Protobuf.Any + alias Runtime.Util + + @type t :: map() + @type command_type :: :payload | :metadata | :full + + @spec decode(t(), ActionReponse.t()) :: term() + def decode(%{output_type: output_mod}, %ActionResponse{response: {_action, payload}}) do + decode_payload(output_mod, payload) + end + + @spec build_msg(t(), command_type()) :: ActionComand.t() + def build_msg(ctx, command_type \\ :full) + + def build_msg(ctx, :full) do + cmd = build_msg(ctx, :metadata) + + %{cmd | payload: build_payload(ctx)} + end + + def build_msg(%{service_name: service_name, original_method: original_method}, :metadata) do + ActionCommand.new( + service_name: service_name, + name: original_method, + metadata: Metadata.new() + ) + end + + def build_msg(%{service_name: service_name, original_method: original_method} = ctx, :payload) do + ActionCommand.new( + service_name: service_name, + name: original_method, + metadata: Metadata.new(), + payload: build_payload(ctx) + ) + end + + @spec build_stream(t()) :: Enumerable.t() + def build_stream( + %{service_name: service_name, original_method: original_method, message: msgs} = state + ) do + # The first message in will contain the request metadata, including the + # service name and command name. It will not have an associated payload set. + # This will be followed by zero to many messages in with a payload + init_command = [ + ActionCommand.new( + service_name: service_name, + name: original_method, + metadata: Metadata.new() + ) + ] + + init_command + |> Stream.concat(msgs) + # Need to signal end_of_stream so attach a token to + # end of the stream so that we can call `GRPC.Stub.end_stream` + |> Stream.concat([:halt]) + |> Stream.transform({:pre_send, state}, &transform/2) + end + + defp transform(:halt, _acc) do + {[:halt], :halt} + end + + defp transform(_msg, {:pre_send, state}) do + command = build_msg(state, :metadata) + + {[command], {:sending, state}} + end + + defp transform(msg, {:sending, state} = acc) do + command = build_msg(%{state | message: msg}, :payload) + {[command], acc} + end + + defp build_payload(%{input_type: input_type, message: msg}) when is_binary(input_type), do: msg + + defp build_payload(%{input_type: input_type, message: msg}) when is_atom(input_type), + do: + Any.new( + type_url: Util.get_type_url(input_type), + value: input_type.encode(msg) + ) + + # defp decode_payload(output_mod, %{payload: %Any{value: bin}}) when is_binary(output_mod) do + # mod = + # Any.new( + # type_url: Util.get_type_url("type.googleapis.com/cloudstate.tck.model.action.Response"), + # value: bin + # ) + + # mod.decode(bin) + # end + + defp decode_payload(output_mod, %{payload: %Any{value: bin}}) when is_atom(output_mod), + do: output_mod.decode(bin) +end diff --git a/apps/runtime_grpc/lib/runtime_grpc.ex b/apps/runtime_grpc/lib/runtime_grpc.ex index 7d86f5a..ed81550 100644 --- a/apps/runtime_grpc/lib/runtime_grpc.ex +++ b/apps/runtime_grpc/lib/runtime_grpc.ex @@ -1,18 +1,5 @@ -defmodule RuntimeGrpc do +defmodule Runtime.GRPC do @moduledoc """ - Documentation for `RuntimeGrpc`. + Documentation for `Runtime.Grpc`. """ - - @doc """ - Hello world. - - ## Examples - - iex> RuntimeGrpc.hello() - :world - - """ - def hello do - :world - end end diff --git a/apps/runtime_grpc/mix.exs b/apps/runtime_grpc/mix.exs index 0676d6b..89678b7 100644 --- a/apps/runtime_grpc/mix.exs +++ b/apps/runtime_grpc/mix.exs @@ -25,6 +25,8 @@ defmodule RuntimeGrpc.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ + {:cloudstate_protocol, in_umbrella: true}, + {:eigr_protocol, in_umbrella: true}, {:runtime, in_umbrella: true} ] end diff --git a/apps/runtime_grpc/test/runtime_grpc_test.exs b/apps/runtime_grpc/test/runtime_grpc_test.exs index d445b45..da1c4ca 100644 --- a/apps/runtime_grpc/test/runtime_grpc_test.exs +++ b/apps/runtime_grpc/test/runtime_grpc_test.exs @@ -1,8 +1,4 @@ -defmodule RuntimeGrpcTest do +defmodule Runtime.GRPCTest do use ExUnit.Case - doctest RuntimeGrpc - - test "greets the world" do - assert RuntimeGrpc.hello() == :world - end + doctest Runtime.GRPC end From b53201140dc1e866a157b90dfea98f4fb4ec754e Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Mon, 21 Feb 2022 19:12:44 -0300 Subject: [PATCH 15/19] Fix. https://github.com/eigr/massa/issues/120 --- apps/massa_proxy/mix.exs | 10 ++++++++-- apps/massa_proxy/test/test_helper.exs | 7 +++++++ mix.exs | 7 +++++-- mix.lock | 2 ++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/apps/massa_proxy/mix.exs b/apps/massa_proxy/mix.exs index 4f3d811..d81ca43 100644 --- a/apps/massa_proxy/mix.exs +++ b/apps/massa_proxy/mix.exs @@ -12,7 +12,10 @@ defmodule MassaProxy.MixProject do lockfile: "../../mix.lock", start_permanent: Mix.env() == :prod, deps: deps(), - releases: releases() + releases: releases(), + aliases: [ + test: "test --no-start" + ] ] end @@ -58,7 +61,10 @@ defmodule MassaProxy.MixProject do # Best practices {:credo, "~> 1.5", only: [:dev, :test], runtime: false}, - {:churn, "~> 0.1", only: :dev} + {:churn, "~> 0.1", only: :dev}, + + # Tests + {:local_cluster, "~> 1.2", only: [:test]} ] end diff --git a/apps/massa_proxy/test/test_helper.exs b/apps/massa_proxy/test/test_helper.exs index 869559e..dbed203 100644 --- a/apps/massa_proxy/test/test_helper.exs +++ b/apps/massa_proxy/test/test_helper.exs @@ -1 +1,8 @@ +# start the current node as a manager +:ok = LocalCluster.start() + +# start your application tree manually +Application.ensure_all_started(:massa_proxy) + +# run all tests! ExUnit.start() diff --git a/mix.exs b/mix.exs index 1c9c10a..27045d6 100644 --- a/mix.exs +++ b/mix.exs @@ -1,4 +1,4 @@ -defmodule MongooseProxyProject.MixProject do +defmodule Massa.MixProject do use Mix.Project def project do @@ -6,7 +6,10 @@ defmodule MongooseProxyProject.MixProject do apps_path: "apps", version: "0.1.0", start_permanent: Mix.env() == :prod, - deps: deps() + deps: deps(), + aliases: [ + test: "test --no-start" + ] ] end diff --git a/mix.lock b/mix.lock index 2dcf416..d427a70 100644 --- a/mix.lock +++ b/mix.lock @@ -16,6 +16,7 @@ "flow": {:hex, :flow, "1.1.0", "b569c1042cb2da97103f6d70a0267a5657dce1402f41b4020bef98bbef9c7c1e", [:mix], [{:gen_stage, "~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}], "hexpm", "066f42f7a1ea6a86cb4ef763310338981a5cfb93bcebce10863a23a4859fd785"}, "gen_stage": {:hex, :gen_stage, "1.1.0", "dd0c0f8d2f3b993fdbd3d58e94abbe65380f4e78bdee3fa93d5618d7d14abe60", [:mix], [], "hexpm", "7f2b36a6d02f7ef2ba410733b540ec423af65ec9c99f3d1083da508aca3b9305"}, "gen_state_machine": {:hex, :gen_state_machine, "3.0.0", "1e57f86a494e5c6b14137ebef26a7eb342b3b0070c7135f2d6768ed3f6b6cdff", [:mix], [], "hexpm", "0a59652574bebceb7309f6b749d2a41b45fdeda8dbb4da0791e355dd19f0ed15"}, + "global_flags": {:hex, :global_flags, "1.0.0", "ee6b864979a1fb38d1fbc67838565644baf632212bce864adca21042df036433", [:rebar3], [], "hexpm", "85d944cecd0f8f96b20ce70b5b16ebccedfcd25e744376b131e89ce61ba93176"}, "google_protos": {:hex, :google_protos, "0.2.0", "7c6280e288d7f04a58448444b12d937ddc8cc40dc3d1e4f61c69936ef71d4739", [:mix], [{:protobuf, "~> 0.8", [hex: :protobuf, repo: "hexpm", optional: false]}], "hexpm", "5de24802e89867cea544d0ee8cbd36f6c9c1ebd4a9fcc55276d6eeadeedcc1f5"}, "grpc": {:git, "https://github.com/elixir-grpc/grpc.git", "eff8a8828d27ddd7f63a3c1dd5aae86246df215e", []}, "grpc_prometheus": {:hex, :grpc_prometheus, "0.1.0", "a2f45ca83018c4ae59e4c293b7455634ac09e38c36cba7cc1fb8affdf462a6d5", [:mix], [{:grpc, ">= 0.0.0", [hex: :grpc, repo: "hexpm", optional: true]}, {:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm", "8b9ab3098657e7daec0b3edc78e1d02418bc0871618d8ca89b51b74a8086bb71"}, @@ -27,6 +28,7 @@ "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"}, "libcluster": {:hex, :libcluster, "3.3.0", "f7d45ff56d88e9fb4c30aee662480cbab69ebc0e7f7da4ad8d01b1e4f7492da8", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "ecdcdc88334ec8eb18b10a13a1d5f22a3319a970b5b1e66cfe71c7719a4ab6cc"}, "libring": {:hex, :libring, "1.5.0", "44313eb6862f5c9168594a061e9d5f556a9819da7c6444706a9e2da533396d70", [:mix], [], "hexpm", "04e843d4fdcff49a62d8e03778d17c6cb2a03fe2d14020d3825a1761b55bd6cc"}, + "local_cluster": {:hex, :local_cluster, "1.2.1", "8eab3b8a387680f0872eacfb1a8bd5a91cb1d4d61256eec6a655b07ac7030c73", [:mix], [{:global_flags, "~> 1.0", [hex: :global_flags, repo: "hexpm", optional: false]}], "hexpm", "aae80c9bc92c911cb0be085fdeea2a9f5b88f81b6bec2ff1fec244bb0acc232c"}, "merkle_map": {:hex, :merkle_map, "0.2.1", "01a88c87a6b9fb594c67c17ebaf047ee55ffa34e74297aa583ed87148006c4c8", [:mix], [], "hexpm", "fed4d143a5c8166eee4fa2b49564f3c4eace9cb252f0a82c1613bba905b2d04d"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "2.0.1", "0de4c81303fe07806ebc2494d5321ce8fb4df106e34dd5f9d787b637ebadc256", [:mix], [], "hexpm", "7a86b920d2aedce5fb6280ac8261ac1a739ae6c1a1ad38f5eadf910063008942"}, From fba7467ebcaf69105237f2bfce6de5d073c8a564 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Tue, 22 Feb 2022 19:09:21 -0300 Subject: [PATCH 16/19] Use do_init/1 on Middleware init/1 --- apps/runtime/lib/protocol/middleware.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/runtime/lib/protocol/middleware.ex b/apps/runtime/lib/protocol/middleware.ex index 8bfa3f0..237a695 100644 --- a/apps/runtime/lib/protocol/middleware.ex +++ b/apps/runtime/lib/protocol/middleware.ex @@ -29,7 +29,7 @@ defmodule Runtime.Protocol.Middleware do @callback handle_stream_out(any(), any()) :: {:ok, Stream.t()} | {:error, any()} - def do_init(state), do: {:ok, state} + def do_init(state), do: {:ok, state, :hibernate} def handle_effect(_context) do raise "Not implemented" @@ -85,7 +85,7 @@ defmodule Runtime.Protocol.Middleware do @impl true def init(state) do - {:ok, state} + do_init(state) end @impl true From 5d272e66c27a63b95bdc3763a2e94ef9e2ddea23 Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Sat, 26 Feb 2022 11:25:11 -0300 Subject: [PATCH 17/19] Refactor. Part Two --- .gitignore | 2 + .../lib/cloudstate/entity_key.pb.ex | 5 - .../lib/cloudstate/eventing.pb.ex | 28 +- .../lib/google/api/annotations.pb.ex | 9 - .../lib/google/api/auth.pb.ex | 45 +- .../lib/google/api/http.pb.ex | 34 +- .../lib/google/api/httpbody.pb.ex | 7 +- .../lib/google/api/source_info.pb.ex | 3 +- .../grpc/reflection/v1alpha/reflection.pb.ex | 66 +-- .../protos/protocol/cloudstate/function.proto | 61 -- apps/eigr_protocol/compile-pb.sh | 23 + apps/eigr_protocol/fetch-cloudstate-pb.sh | 32 ++ .../lib/cloudstate/entity_key.pb.ex | 0 .../lib/cloudstate/eventing.pb.ex | 74 +++ .../lib/eigr/functions/protocol/action.pb.ex | 129 +++++ .../lib/eigr/functions/protocol/entity.pb.ex | 537 ++++++++++++++++++ .../eigr/functions/protocol/entity_key.pb.ex | 0 .../functions/protocol/event_sourced.pb.ex | 216 +++++++ .../eigr/functions/protocol/eventing.pb.ex | 77 +++ .../functions/protocol/value_entity.pb.ex | 244 ++++++++ .../lib/google/api/annotations.pb.ex | 0 apps/eigr_protocol/lib/google/api/auth.pb.ex | 175 ++++++ apps/eigr_protocol/lib/google/api/http.pb.ex | 98 ++++ .../lib/google/api/httpbody.pb.ex | 27 + .../lib/google/api/source_info.pb.ex | 21 + .../grpc/reflection/v1alpha/reflection.pb.ex | 278 +++++++++ apps/eigr_protocol/mix.exs | 7 +- .../shoppingcart/persistence/domain.proto | 27 + .../example/shoppingcart/shoppingcart.proto | 63 ++ .../frontend/google/api/annotations.proto | 32 ++ .../functions/frontend/google/api/auth.proto | 228 ++++++++ .../functions/frontend/google/api/http.proto | 377 ++++++++++++ .../frontend/google/api/httpbody.proto | 77 +++ .../frontend/google/api/source_info.proto | 31 + .../functions/protocol/eigr}/action.proto | 21 +- .../eigr/functions/protocol/eigr}/crdt.proto | 24 +- .../functions/protocol/eigr}/entity.proto | 11 +- .../functions/protocol/eigr/entity_key.proto | 30 + .../protocol/eigr}/event_sourced.proto | 8 +- .../functions/protocol/eigr/eventing.proto | 76 +++ .../protocol/eigr}/value_entity.proto | 8 +- .../grpc/reflection/v1alpha/reflection.proto | 136 +++++ apps/runtime/lib/protocol/middleware.ex | 13 +- .../lib/protocol/middleware_supervisor.ex | 17 + apps/runtime/lib/runtime.ex | 73 ++- .../lib/protocol/action/action_middleware.ex | 3 +- .../{processor.ex => action_processor.ex} | 0 .../{protocol.ex => action_protocol.ex} | 0 48 files changed, 3207 insertions(+), 246 deletions(-) delete mode 100644 apps/cloudstate_protocol/priv/protos/protocol/cloudstate/function.proto create mode 100755 apps/eigr_protocol/compile-pb.sh create mode 100755 apps/eigr_protocol/fetch-cloudstate-pb.sh create mode 100644 apps/eigr_protocol/lib/cloudstate/entity_key.pb.ex create mode 100644 apps/eigr_protocol/lib/cloudstate/eventing.pb.ex create mode 100644 apps/eigr_protocol/lib/eigr/functions/protocol/action.pb.ex create mode 100644 apps/eigr_protocol/lib/eigr/functions/protocol/entity.pb.ex create mode 100644 apps/eigr_protocol/lib/eigr/functions/protocol/entity_key.pb.ex create mode 100644 apps/eigr_protocol/lib/eigr/functions/protocol/event_sourced.pb.ex create mode 100644 apps/eigr_protocol/lib/eigr/functions/protocol/eventing.pb.ex create mode 100644 apps/eigr_protocol/lib/eigr/functions/protocol/value_entity.pb.ex create mode 100644 apps/eigr_protocol/lib/google/api/annotations.pb.ex create mode 100644 apps/eigr_protocol/lib/google/api/auth.pb.ex create mode 100644 apps/eigr_protocol/lib/google/api/http.pb.ex create mode 100644 apps/eigr_protocol/lib/google/api/httpbody.pb.ex create mode 100644 apps/eigr_protocol/lib/google/api/source_info.pb.ex create mode 100644 apps/eigr_protocol/lib/grpc/reflection/v1alpha/reflection.pb.ex create mode 100644 apps/eigr_protocol/priv/protos/eigr/functions/example/shoppingcart/persistence/domain.proto create mode 100644 apps/eigr_protocol/priv/protos/eigr/functions/example/shoppingcart/shoppingcart.proto create mode 100644 apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/annotations.proto create mode 100644 apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/auth.proto create mode 100644 apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/http.proto create mode 100644 apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/httpbody.proto create mode 100644 apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/source_info.proto rename apps/{cloudstate_protocol/priv/protos/protocol/cloudstate => eigr_protocol/priv/protos/eigr/functions/protocol/eigr}/action.proto (87%) rename apps/{cloudstate_protocol/priv/protos/protocol/cloudstate => eigr_protocol/priv/protos/eigr/functions/protocol/eigr}/crdt.proto (94%) rename apps/{cloudstate_protocol/priv/protos/protocol/cloudstate => eigr_protocol/priv/protos/eigr/functions/protocol/eigr}/entity.proto (97%) create mode 100644 apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/entity_key.proto rename apps/{cloudstate_protocol/priv/protos/protocol/cloudstate => eigr_protocol/priv/protos/eigr/functions/protocol/eigr}/event_sourced.proto (95%) create mode 100644 apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/eventing.proto rename apps/{cloudstate_protocol/priv/protos/protocol/cloudstate => eigr_protocol/priv/protos/eigr/functions/protocol/eigr}/value_entity.proto (94%) create mode 100644 apps/eigr_protocol/priv/protos/eigr/functions/proxy/grpc/reflection/v1alpha/reflection.proto create mode 100644 apps/runtime/lib/protocol/middleware_supervisor.ex rename apps/runtime_grpc/lib/protocol/action/{processor.ex => action_processor.ex} (100%) rename apps/runtime_grpc/lib/protocol/action/{protocol.ex => action_protocol.ex} (100%) diff --git a/.gitignore b/.gitignore index 74d6f3b..77f3986 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.vscode/* + # The directory Mix will write compiled artifacts to. /_build/ diff --git a/apps/cloudstate_protocol/lib/cloudstate/entity_key.pb.ex b/apps/cloudstate_protocol/lib/cloudstate/entity_key.pb.ex index 4b03647..e69de29 100644 --- a/apps/cloudstate_protocol/lib/cloudstate/entity_key.pb.ex +++ b/apps/cloudstate_protocol/lib/cloudstate/entity_key.pb.ex @@ -1,5 +0,0 @@ -defmodule Cloudstate.PbExtension do - @moduledoc false - use Protobuf, syntax: :proto3 - extend(Google.Protobuf.FieldOptions, :entity_key, 1080, optional: true, type: :bool) -end diff --git a/apps/cloudstate_protocol/lib/cloudstate/eventing.pb.ex b/apps/cloudstate_protocol/lib/cloudstate/eventing.pb.ex index 663a009..a767df1 100644 --- a/apps/cloudstate_protocol/lib/cloudstate/eventing.pb.ex +++ b/apps/cloudstate_protocol/lib/cloudstate/eventing.pb.ex @@ -6,7 +6,6 @@ defmodule Cloudstate.Eventing do in: Cloudstate.EventSource.t() | nil, out: Cloudstate.EventDestination.t() | nil } - defstruct [:in, :out] def descriptor do @@ -20,8 +19,8 @@ defmodule Cloudstate.Eventing do ) end - field(:in, 1, type: Cloudstate.EventSource) - field(:out, 2, type: Cloudstate.EventDestination) + field :in, 1, type: Cloudstate.EventSource + field :out, 2, type: Cloudstate.EventDestination end defmodule Cloudstate.EventSource do @@ -32,7 +31,6 @@ defmodule Cloudstate.EventSource do source: {atom, any}, consumer_group: String.t() } - defstruct [:source, :consumer_group] def descriptor do @@ -47,11 +45,10 @@ defmodule Cloudstate.EventSource do ) end - oneof(:source, 0) - - field(:consumer_group, 1, type: :string) - field(:topic, 2, type: :string, oneof: 0) - field(:event_log, 3, type: :string, oneof: 0) + oneof :source, 0 + field :consumer_group, 1, type: :string + field :topic, 2, type: :string, oneof: 0 + field :event_log, 3, type: :string, oneof: 0 end defmodule Cloudstate.EventDestination do @@ -61,7 +58,6 @@ defmodule Cloudstate.EventDestination do @type t :: %__MODULE__{ destination: {atom, any} } - defstruct [:destination] def descriptor do @@ -73,14 +69,6 @@ defmodule Cloudstate.EventDestination do ) end - oneof(:destination, 0) - - field(:topic, 1, type: :string, oneof: 0) -end - -defmodule Cloudstate.PbExtension do - @moduledoc false - use Protobuf, syntax: :proto3 - - extend(Google.Protobuf.MethodOptions, :eventing, 1081, optional: true, type: Cloudstate.Eventing) + oneof :destination, 0 + field :topic, 1, type: :string, oneof: 0 end diff --git a/apps/cloudstate_protocol/lib/google/api/annotations.pb.ex b/apps/cloudstate_protocol/lib/google/api/annotations.pb.ex index 2aa2341..e69de29 100644 --- a/apps/cloudstate_protocol/lib/google/api/annotations.pb.ex +++ b/apps/cloudstate_protocol/lib/google/api/annotations.pb.ex @@ -1,9 +0,0 @@ -defmodule Google.Api.PbExtension do - @moduledoc false - use Protobuf, syntax: :proto3 - - extend(Google.Protobuf.MethodOptions, :http, 72_295_728, - optional: true, - type: Google.Api.HttpRule - ) -end diff --git a/apps/cloudstate_protocol/lib/google/api/auth.pb.ex b/apps/cloudstate_protocol/lib/google/api/auth.pb.ex index 0e66549..f2a05b9 100644 --- a/apps/cloudstate_protocol/lib/google/api/auth.pb.ex +++ b/apps/cloudstate_protocol/lib/google/api/auth.pb.ex @@ -6,7 +6,6 @@ defmodule Google.Api.Authentication do rules: [Google.Api.AuthenticationRule.t()], providers: [Google.Api.AuthProvider.t()] } - defstruct [:rules, :providers] def descriptor do @@ -22,8 +21,8 @@ defmodule Google.Api.Authentication do ) end - field(:rules, 3, repeated: true, type: Google.Api.AuthenticationRule) - field(:providers, 4, repeated: true, type: Google.Api.AuthProvider) + field :rules, 3, repeated: true, type: Google.Api.AuthenticationRule + field :providers, 4, repeated: true, type: Google.Api.AuthProvider end defmodule Google.Api.AuthenticationRule do @@ -36,7 +35,6 @@ defmodule Google.Api.AuthenticationRule do allow_without_credential: boolean, requirements: [Google.Api.AuthRequirement.t()] } - defstruct [:selector, :oauth, :allow_without_credential, :requirements] def descriptor do @@ -57,10 +55,10 @@ defmodule Google.Api.AuthenticationRule do ) end - field(:selector, 1, type: :string) - field(:oauth, 2, type: Google.Api.OAuthRequirements) - field(:allow_without_credential, 5, type: :bool) - field(:requirements, 7, repeated: true, type: Google.Api.AuthRequirement) + field :selector, 1, type: :string + field :oauth, 2, type: Google.Api.OAuthRequirements + field :allow_without_credential, 5, type: :bool + field :requirements, 7, repeated: true, type: Google.Api.AuthRequirement end defmodule Google.Api.JwtLocation do @@ -71,7 +69,6 @@ defmodule Google.Api.JwtLocation do in: {atom, any}, value_prefix: String.t() } - defstruct [:in, :value_prefix] def descriptor do @@ -86,11 +83,10 @@ defmodule Google.Api.JwtLocation do ) end - oneof(:in, 0) - - field(:header, 1, type: :string, oneof: 0) - field(:query, 2, type: :string, oneof: 0) - field(:value_prefix, 3, type: :string) + oneof :in, 0 + field :header, 1, type: :string, oneof: 0 + field :query, 2, type: :string, oneof: 0 + field :value_prefix, 3, type: :string end defmodule Google.Api.AuthProvider do @@ -105,7 +101,6 @@ defmodule Google.Api.AuthProvider do authorization_url: String.t(), jwt_locations: [Google.Api.JwtLocation.t()] } - defstruct [:id, :issuer, :jwks_uri, :audiences, :authorization_url, :jwt_locations] def descriptor do @@ -125,12 +120,12 @@ defmodule Google.Api.AuthProvider do ) end - field(:id, 1, type: :string) - field(:issuer, 2, type: :string) - field(:jwks_uri, 3, type: :string) - field(:audiences, 4, type: :string) - field(:authorization_url, 5, type: :string) - field(:jwt_locations, 6, repeated: true, type: Google.Api.JwtLocation) + field :id, 1, type: :string + field :issuer, 2, type: :string + field :jwks_uri, 3, type: :string + field :audiences, 4, type: :string + field :authorization_url, 5, type: :string + field :jwt_locations, 6, repeated: true, type: Google.Api.JwtLocation end defmodule Google.Api.OAuthRequirements do @@ -140,7 +135,6 @@ defmodule Google.Api.OAuthRequirements do @type t :: %__MODULE__{ canonical_scopes: String.t() } - defstruct [:canonical_scopes] def descriptor do @@ -153,7 +147,7 @@ defmodule Google.Api.OAuthRequirements do ) end - field(:canonical_scopes, 1, type: :string) + field :canonical_scopes, 1, type: :string end defmodule Google.Api.AuthRequirement do @@ -164,7 +158,6 @@ defmodule Google.Api.AuthRequirement do provider_id: String.t(), audiences: String.t() } - defstruct [:provider_id, :audiences] def descriptor do @@ -177,6 +170,6 @@ defmodule Google.Api.AuthRequirement do ) end - field(:provider_id, 1, type: :string) - field(:audiences, 2, type: :string) + field :provider_id, 1, type: :string + field :audiences, 2, type: :string end diff --git a/apps/cloudstate_protocol/lib/google/api/http.pb.ex b/apps/cloudstate_protocol/lib/google/api/http.pb.ex index 59bd841..ba11776 100644 --- a/apps/cloudstate_protocol/lib/google/api/http.pb.ex +++ b/apps/cloudstate_protocol/lib/google/api/http.pb.ex @@ -6,7 +6,6 @@ defmodule Google.Api.Http do rules: [Google.Api.HttpRule.t()], fully_decode_reserved_expansion: boolean } - defstruct [:rules, :fully_decode_reserved_expansion] def descriptor do @@ -22,8 +21,8 @@ defmodule Google.Api.Http do ) end - field(:rules, 1, repeated: true, type: Google.Api.HttpRule) - field(:fully_decode_reserved_expansion, 2, type: :bool) + field :rules, 1, repeated: true, type: Google.Api.HttpRule + field :fully_decode_reserved_expansion, 2, type: :bool end defmodule Google.Api.HttpRule do @@ -37,7 +36,6 @@ defmodule Google.Api.HttpRule do response_body: String.t(), additional_bindings: [Google.Api.HttpRule.t()] } - defstruct [:pattern, :selector, :body, :response_body, :additional_bindings] def descriptor do @@ -63,18 +61,17 @@ defmodule Google.Api.HttpRule do ) end - oneof(:pattern, 0) - - field(:selector, 1, type: :string) - field(:get, 2, type: :string, oneof: 0) - field(:put, 3, type: :string, oneof: 0) - field(:post, 4, type: :string, oneof: 0) - field(:delete, 5, type: :string, oneof: 0) - field(:patch, 6, type: :string, oneof: 0) - field(:custom, 8, type: Google.Api.CustomHttpPattern, oneof: 0) - field(:body, 7, type: :string) - field(:response_body, 12, type: :string) - field(:additional_bindings, 11, repeated: true, type: Google.Api.HttpRule) + oneof :pattern, 0 + field :selector, 1, type: :string + field :get, 2, type: :string, oneof: 0 + field :put, 3, type: :string, oneof: 0 + field :post, 4, type: :string, oneof: 0 + field :delete, 5, type: :string, oneof: 0 + field :patch, 6, type: :string, oneof: 0 + field :custom, 8, type: Google.Api.CustomHttpPattern, oneof: 0 + field :body, 7, type: :string + field :response_body, 12, type: :string + field :additional_bindings, 11, repeated: true, type: Google.Api.HttpRule end defmodule Google.Api.CustomHttpPattern do @@ -85,7 +82,6 @@ defmodule Google.Api.CustomHttpPattern do kind: String.t(), path: String.t() } - defstruct [:kind, :path] def descriptor do @@ -97,6 +93,6 @@ defmodule Google.Api.CustomHttpPattern do ) end - field(:kind, 1, type: :string) - field(:path, 2, type: :string) + field :kind, 1, type: :string + field :path, 2, type: :string end diff --git a/apps/cloudstate_protocol/lib/google/api/httpbody.pb.ex b/apps/cloudstate_protocol/lib/google/api/httpbody.pb.ex index 2a435a7..fe675e8 100644 --- a/apps/cloudstate_protocol/lib/google/api/httpbody.pb.ex +++ b/apps/cloudstate_protocol/lib/google/api/httpbody.pb.ex @@ -7,7 +7,6 @@ defmodule Google.Api.HttpBody do data: binary, extensions: [Google.Protobuf.Any.t()] } - defstruct [:content_type, :data, :extensions] def descriptor do @@ -22,7 +21,7 @@ defmodule Google.Api.HttpBody do ) end - field(:content_type, 1, type: :string) - field(:data, 2, type: :bytes) - field(:extensions, 3, repeated: true, type: Google.Protobuf.Any) + field :content_type, 1, type: :string + field :data, 2, type: :bytes + field :extensions, 3, repeated: true, type: Google.Protobuf.Any end diff --git a/apps/cloudstate_protocol/lib/google/api/source_info.pb.ex b/apps/cloudstate_protocol/lib/google/api/source_info.pb.ex index 9c64ca0..c2121b0 100644 --- a/apps/cloudstate_protocol/lib/google/api/source_info.pb.ex +++ b/apps/cloudstate_protocol/lib/google/api/source_info.pb.ex @@ -5,7 +5,6 @@ defmodule Google.Api.SourceInfo do @type t :: %__MODULE__{ source_files: [Google.Protobuf.Any.t()] } - defstruct [:source_files] def descriptor do @@ -18,5 +17,5 @@ defmodule Google.Api.SourceInfo do ) end - field(:source_files, 1, repeated: true, type: Google.Protobuf.Any) + field :source_files, 1, repeated: true, type: Google.Protobuf.Any end diff --git a/apps/cloudstate_protocol/lib/grpc/reflection/v1alpha/reflection.pb.ex b/apps/cloudstate_protocol/lib/grpc/reflection/v1alpha/reflection.pb.ex index 969cd6f..9fb40bc 100644 --- a/apps/cloudstate_protocol/lib/grpc/reflection/v1alpha/reflection.pb.ex +++ b/apps/cloudstate_protocol/lib/grpc/reflection/v1alpha/reflection.pb.ex @@ -6,7 +6,6 @@ defmodule Grpc.Reflection.V1alpha.ServerReflectionRequest do message_request: {atom, any}, host: String.t() } - defstruct [:message_request, :host] def descriptor do @@ -35,14 +34,13 @@ defmodule Grpc.Reflection.V1alpha.ServerReflectionRequest do ) end - oneof(:message_request, 0) - - field(:host, 1, type: :string) - field(:file_by_filename, 3, type: :string, oneof: 0) - field(:file_containing_symbol, 4, type: :string, oneof: 0) - field(:file_containing_extension, 5, type: Grpc.Reflection.V1alpha.ExtensionRequest, oneof: 0) - field(:all_extension_numbers_of_type, 6, type: :string, oneof: 0) - field(:list_services, 7, type: :string, oneof: 0) + oneof :message_request, 0 + field :host, 1, type: :string + field :file_by_filename, 3, type: :string, oneof: 0 + field :file_containing_symbol, 4, type: :string, oneof: 0 + field :file_containing_extension, 5, type: Grpc.Reflection.V1alpha.ExtensionRequest, oneof: 0 + field :all_extension_numbers_of_type, 6, type: :string, oneof: 0 + field :list_services, 7, type: :string, oneof: 0 end defmodule Grpc.Reflection.V1alpha.ExtensionRequest do @@ -53,7 +51,6 @@ defmodule Grpc.Reflection.V1alpha.ExtensionRequest do containing_type: String.t(), extension_number: integer } - defstruct [:containing_type, :extension_number] def descriptor do @@ -68,8 +65,8 @@ defmodule Grpc.Reflection.V1alpha.ExtensionRequest do ) end - field(:containing_type, 1, type: :string) - field(:extension_number, 2, type: :int32) + field :containing_type, 1, type: :string + field :extension_number, 2, type: :int32 end defmodule Grpc.Reflection.V1alpha.ServerReflectionResponse do @@ -81,7 +78,6 @@ defmodule Grpc.Reflection.V1alpha.ServerReflectionResponse do valid_host: String.t(), original_request: Grpc.Reflection.V1alpha.ServerReflectionRequest.t() | nil } - defstruct [:message_response, :valid_host, :original_request] def descriptor do @@ -121,23 +117,20 @@ defmodule Grpc.Reflection.V1alpha.ServerReflectionResponse do ) end - oneof(:message_response, 0) - - field(:valid_host, 1, type: :string) - field(:original_request, 2, type: Grpc.Reflection.V1alpha.ServerReflectionRequest) + oneof :message_response, 0 + field :valid_host, 1, type: :string + field :original_request, 2, type: Grpc.Reflection.V1alpha.ServerReflectionRequest - field(:file_descriptor_response, 4, + field :file_descriptor_response, 4, type: Grpc.Reflection.V1alpha.FileDescriptorResponse, oneof: 0 - ) - field(:all_extension_numbers_response, 5, + field :all_extension_numbers_response, 5, type: Grpc.Reflection.V1alpha.ExtensionNumberResponse, oneof: 0 - ) - field(:list_services_response, 6, type: Grpc.Reflection.V1alpha.ListServiceResponse, oneof: 0) - field(:error_response, 7, type: Grpc.Reflection.V1alpha.ErrorResponse, oneof: 0) + field :list_services_response, 6, type: Grpc.Reflection.V1alpha.ListServiceResponse, oneof: 0 + field :error_response, 7, type: Grpc.Reflection.V1alpha.ErrorResponse, oneof: 0 end defmodule Grpc.Reflection.V1alpha.FileDescriptorResponse do @@ -147,7 +140,6 @@ defmodule Grpc.Reflection.V1alpha.FileDescriptorResponse do @type t :: %__MODULE__{ file_descriptor_proto: [binary] } - defstruct [:file_descriptor_proto] def descriptor do @@ -160,7 +152,7 @@ defmodule Grpc.Reflection.V1alpha.FileDescriptorResponse do ) end - field(:file_descriptor_proto, 1, repeated: true, type: :bytes) + field :file_descriptor_proto, 1, repeated: true, type: :bytes end defmodule Grpc.Reflection.V1alpha.ExtensionNumberResponse do @@ -171,7 +163,6 @@ defmodule Grpc.Reflection.V1alpha.ExtensionNumberResponse do base_type_name: String.t(), extension_number: [integer] } - defstruct [:base_type_name, :extension_number] def descriptor do @@ -186,8 +177,8 @@ defmodule Grpc.Reflection.V1alpha.ExtensionNumberResponse do ) end - field(:base_type_name, 1, type: :string) - field(:extension_number, 2, repeated: true, type: :int32) + field :base_type_name, 1, type: :string + field :extension_number, 2, repeated: true, type: :int32 end defmodule Grpc.Reflection.V1alpha.ListServiceResponse do @@ -197,7 +188,6 @@ defmodule Grpc.Reflection.V1alpha.ListServiceResponse do @type t :: %__MODULE__{ service: [Grpc.Reflection.V1alpha.ServiceResponse.t()] } - defstruct [:service] def descriptor do @@ -211,7 +201,7 @@ defmodule Grpc.Reflection.V1alpha.ListServiceResponse do ) end - field(:service, 1, repeated: true, type: Grpc.Reflection.V1alpha.ServiceResponse) + field :service, 1, repeated: true, type: Grpc.Reflection.V1alpha.ServiceResponse end defmodule Grpc.Reflection.V1alpha.ServiceResponse do @@ -221,7 +211,6 @@ defmodule Grpc.Reflection.V1alpha.ServiceResponse do @type t :: %__MODULE__{ name: String.t() } - defstruct [:name] def descriptor do @@ -232,7 +221,7 @@ defmodule Grpc.Reflection.V1alpha.ServiceResponse do ) end - field(:name, 1, type: :string) + field :name, 1, type: :string end defmodule Grpc.Reflection.V1alpha.ErrorResponse do @@ -243,7 +232,6 @@ defmodule Grpc.Reflection.V1alpha.ErrorResponse do error_code: integer, error_message: String.t() } - defstruct [:error_code, :error_message] def descriptor do @@ -257,8 +245,8 @@ defmodule Grpc.Reflection.V1alpha.ErrorResponse do ) end - field(:error_code, 1, type: :int32) - field(:error_message, 2, type: :string) + field :error_code, 1, type: :int32 + field :error_message, 2, type: :string end defmodule Grpc.Reflection.V1alpha.ServerReflection.Service do @@ -279,11 +267,9 @@ defmodule Grpc.Reflection.V1alpha.ServerReflection.Service do ) end - rpc( - :ServerReflectionInfo, - stream(Grpc.Reflection.V1alpha.ServerReflectionRequest), - stream(Grpc.Reflection.V1alpha.ServerReflectionResponse) - ) + rpc :ServerReflectionInfo, + stream(Grpc.Reflection.V1alpha.ServerReflectionRequest), + stream(Grpc.Reflection.V1alpha.ServerReflectionResponse) end defmodule Grpc.Reflection.V1alpha.ServerReflection.Stub do diff --git a/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/function.proto b/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/function.proto deleted file mode 100644 index d0e54ea..0000000 --- a/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/function.proto +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2019 Lightbend Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// gRPC interface for Stateless Entity user functions. - -syntax = "proto3"; - -package cloudstate.function; - -// Any is used so that domain events defined according to the functions business domain can be embedded inside -// the protocol. -import "google/protobuf/any.proto"; -import "cloudstate/entity.proto"; - -option java_package = "io.cloudstate.protocol"; -option go_package = "cloudstate/protocol"; - -message FunctionCommand { - // The name of the service this function is on. - string service_name = 2; - - // Command name - string name = 3; - - // The command payload. - google.protobuf.Any payload = 4; -} - -message FunctionReply { - - oneof response { - Failure failure = 1; - Reply reply = 2; - Forward forward = 3; - } - - repeated SideEffect side_effects = 4; -} - -service StatelessFunction { - - rpc handleUnary(FunctionCommand) returns (FunctionReply) {} - - rpc handleStreamedIn(stream FunctionCommand) returns (FunctionReply) {} - - rpc handleStreamedOut(FunctionCommand) returns (stream FunctionReply) {} - - rpc handleStreamed(stream FunctionCommand) returns (stream FunctionReply) {} - -} diff --git a/apps/eigr_protocol/compile-pb.sh b/apps/eigr_protocol/compile-pb.sh new file mode 100755 index 0000000..f02c657 --- /dev/null +++ b/apps/eigr_protocol/compile-pb.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +set -o nounset +set -o errexit +set -o pipefail + +# CloudState Protocol + +protoc --elixir_out=gen_descriptors=true,plugins=grpc:./lib --proto_path=priv/protos/eigr/functions/proxy/ priv/protos/eigr/functions/proxy/grpc/reflection/v1alpha/reflection.proto + +protoc --elixir_out=gen_descriptors=true,plugins=grpc:./lib --proto_path=priv/protos/eigr/functions/frontend/ priv/protos/eigr/functions/frontend/google/api/http.proto +protoc --elixir_out=gen_descriptors=true,plugins=grpc:./lib --proto_path=priv/protos/eigr/functions/frontend/ priv/protos/eigr/functions/frontend/google/api/annotations.proto +protoc --elixir_out=gen_descriptors=true,plugins=grpc:./lib --proto_path=priv/protos/eigr/functions/frontend/ priv/protos/eigr/functions/frontend/google/api/httpbody.proto +protoc --elixir_out=gen_descriptors=true,plugins=grpc:./lib --proto_path=priv/protos/eigr/functions/frontend/ priv/protos/eigr/functions/frontend/google/api/auth.proto +protoc --elixir_out=gen_descriptors=true,plugins=grpc:./lib --proto_path=priv/protos/eigr/functions/frontend/ priv/protos/eigr/functions/frontend/google/api/source_info.proto + +protoc --elixir_out=gen_descriptors=true:./lib/eigr/functions/protocol --proto_path=priv/protos/eigr/functions/protocol/eigr/ priv/protos/eigr/functions/protocol/eigr/eventing.proto +protoc --elixir_out=gen_descriptors=true:./lib/eigr/functions/protocol --proto_path=priv/protos/eigr/functions/protocol/eigr/ priv/protos/eigr/functions/protocol/eigr/entity_key.proto + +protoc --elixir_out=gen_descriptors=true,plugins=grpc:./lib/eigr/functions/protocol --proto_path=priv/protos/eigr/functions/protocol/eigr/ priv/protos/eigr/functions/protocol/eigr/entity.proto +protoc --elixir_out=gen_descriptors=true,plugins=grpc:./lib/eigr/functions/protocol --proto_path=priv/protos/eigr/functions/protocol/eigr/ priv/protos/eigr/functions/protocol/eigr/event_sourced.proto +protoc --elixir_out=gen_descriptors=true,plugins=grpc:./lib/eigr/functions/protocol --proto_path=priv/protos/eigr/functions/protocol/eigr/ priv/protos/eigr/functions/protocol/eigr/action.proto +protoc --elixir_out=gen_descriptors=true,plugins=grpc:./lib/eigr/functions/protocol --proto_path=priv/protos/eigr/functions/protocol/eigr/ priv/protos/eigr/functions/protocol/eigr/value_entity.proto diff --git a/apps/eigr_protocol/fetch-cloudstate-pb.sh b/apps/eigr_protocol/fetch-cloudstate-pb.sh new file mode 100755 index 0000000..371ac82 --- /dev/null +++ b/apps/eigr_protocol/fetch-cloudstate-pb.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +set -o nounset +set -o errexit +set -o pipefail + +function fetch() { + local path=$1 + local tag=$2 + mkdir -p "priv/protos/$(dirname $path)" + curl -o "priv/protos/${path}" "https://raw.githubusercontent.com/cloudstateio/cloudstate/${tag}/protocols/${path}" +} + +tag=$1 + +# CloudState protocol +fetch "protocol/cloudstate/entity.proto" "${tag}" +fetch "protocol/cloudstate/event_sourced.proto" "${tag}" +fetch "protocol/cloudstate/function.proto" "${tag}" +fetch "protocol/cloudstate/crdt.proto" "${tag}" + +# TCK shopping cart example +fetch "example/shoppingcart/shoppingcart.proto" "${tag}" +fetch "example/shoppingcart/persistence/domain.proto" "${tag}" + +# CloudState frontend +fetch "frontend/cloudstate/entity_key.proto" "${tag}" + +# dependencies +fetch "proxy/grpc/reflection/v1alpha/reflection.proto" "${tag}" +fetch "frontend/google/api/annotations.proto" "${tag}" +fetch "frontend/google/api/http.proto" "${tag}" \ No newline at end of file diff --git a/apps/eigr_protocol/lib/cloudstate/entity_key.pb.ex b/apps/eigr_protocol/lib/cloudstate/entity_key.pb.ex new file mode 100644 index 0000000..e69de29 diff --git a/apps/eigr_protocol/lib/cloudstate/eventing.pb.ex b/apps/eigr_protocol/lib/cloudstate/eventing.pb.ex new file mode 100644 index 0000000..a767df1 --- /dev/null +++ b/apps/eigr_protocol/lib/cloudstate/eventing.pb.ex @@ -0,0 +1,74 @@ +defmodule Cloudstate.Eventing do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + in: Cloudstate.EventSource.t() | nil, + out: Cloudstate.EventDestination.t() | nil + } + defstruct [:in, :out] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 8, 69, 118, 101, 110, 116, 105, 110, 103, 18, 39, 10, 2, 105, 110, 24, 1, 32, 1, 40, + 11, 50, 23, 46, 99, 108, 111, 117, 100, 115, 116, 97, 116, 101, 46, 69, 118, 101, 110, + 116, 83, 111, 117, 114, 99, 101, 82, 2, 105, 110, 18, 46, 10, 3, 111, 117, 116, 24, 2, 32, + 1, 40, 11, 50, 28, 46, 99, 108, 111, 117, 100, 115, 116, 97, 116, 101, 46, 69, 118, 101, + 110, 116, 68, 101, 115, 116, 105, 110, 97, 116, 105, 111, 110, 82, 3, 111, 117, 116>> + ) + end + + field :in, 1, type: Cloudstate.EventSource + field :out, 2, type: Cloudstate.EventDestination +end + +defmodule Cloudstate.EventSource do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + source: {atom, any}, + consumer_group: String.t() + } + defstruct [:source, :consumer_group] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 11, 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 18, 37, 10, 14, 99, 111, 110, + 115, 117, 109, 101, 114, 95, 103, 114, 111, 117, 112, 24, 1, 32, 1, 40, 9, 82, 13, 99, + 111, 110, 115, 117, 109, 101, 114, 71, 114, 111, 117, 112, 18, 22, 10, 5, 116, 111, 112, + 105, 99, 24, 2, 32, 1, 40, 9, 72, 0, 82, 5, 116, 111, 112, 105, 99, 18, 29, 10, 9, 101, + 118, 101, 110, 116, 95, 108, 111, 103, 24, 3, 32, 1, 40, 9, 72, 0, 82, 8, 101, 118, 101, + 110, 116, 76, 111, 103, 66, 8, 10, 6, 115, 111, 117, 114, 99, 101>> + ) + end + + oneof :source, 0 + field :consumer_group, 1, type: :string + field :topic, 2, type: :string, oneof: 0 + field :event_log, 3, type: :string, oneof: 0 +end + +defmodule Cloudstate.EventDestination do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + destination: {atom, any} + } + defstruct [:destination] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 16, 69, 118, 101, 110, 116, 68, 101, 115, 116, 105, 110, 97, 116, 105, 111, 110, 18, + 22, 10, 5, 116, 111, 112, 105, 99, 24, 1, 32, 1, 40, 9, 72, 0, 82, 5, 116, 111, 112, 105, + 99, 66, 13, 10, 11, 100, 101, 115, 116, 105, 110, 97, 116, 105, 111, 110>> + ) + end + + oneof :destination, 0 + field :topic, 1, type: :string, oneof: 0 +end diff --git a/apps/eigr_protocol/lib/eigr/functions/protocol/action.pb.ex b/apps/eigr_protocol/lib/eigr/functions/protocol/action.pb.ex new file mode 100644 index 0000000..4d53b06 --- /dev/null +++ b/apps/eigr_protocol/lib/eigr/functions/protocol/action.pb.ex @@ -0,0 +1,129 @@ +defmodule Eigr.Functions.Protocol.Action.ActionCommand do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + service_name: String.t(), + name: String.t(), + payload: Google.Protobuf.Any.t() | nil, + metadata: Eigr.Functions.Protocol.Metadata.t() | nil + } + defstruct [:service_name, :name, :payload, :metadata] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 13, 65, 99, 116, 105, 111, 110, 67, 111, 109, 109, 97, 110, 100, 18, 33, 10, 12, 115, + 101, 114, 118, 105, 99, 101, 95, 110, 97, 109, 101, 24, 2, 32, 1, 40, 9, 82, 11, 115, 101, + 114, 118, 105, 99, 101, 78, 97, 109, 101, 18, 18, 10, 4, 110, 97, 109, 101, 24, 3, 32, 1, + 40, 9, 82, 4, 110, 97, 109, 101, 18, 46, 10, 7, 112, 97, 121, 108, 111, 97, 100, 24, 4, + 32, 1, 40, 11, 50, 20, 46, 103, 111, 111, 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, + 117, 102, 46, 65, 110, 121, 82, 7, 112, 97, 121, 108, 111, 97, 100, 18, 61, 10, 8, 109, + 101, 116, 97, 100, 97, 116, 97, 24, 5, 32, 1, 40, 11, 50, 33, 46, 101, 105, 103, 114, 46, + 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, + 77, 101, 116, 97, 100, 97, 116, 97, 82, 8, 109, 101, 116, 97, 100, 97, 116, 97>> + ) + end + + field :service_name, 2, type: :string + field :name, 3, type: :string + field :payload, 4, type: Google.Protobuf.Any + field :metadata, 5, type: Eigr.Functions.Protocol.Metadata +end + +defmodule Eigr.Functions.Protocol.Action.ActionResponse do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + response: {atom, any}, + side_effects: [Eigr.Functions.Protocol.SideEffect.t()] + } + defstruct [:response, :side_effects] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 14, 65, 99, 116, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 18, 60, 10, 7, + 102, 97, 105, 108, 117, 114, 101, 24, 1, 32, 1, 40, 11, 50, 32, 46, 101, 105, 103, 114, + 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, + 46, 70, 97, 105, 108, 117, 114, 101, 72, 0, 82, 7, 102, 97, 105, 108, 117, 114, 101, 18, + 54, 10, 5, 114, 101, 112, 108, 121, 24, 2, 32, 1, 40, 11, 50, 30, 46, 101, 105, 103, 114, + 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, + 46, 82, 101, 112, 108, 121, 72, 0, 82, 5, 114, 101, 112, 108, 121, 18, 60, 10, 7, 102, + 111, 114, 119, 97, 114, 100, 24, 3, 32, 1, 40, 11, 50, 32, 46, 101, 105, 103, 114, 46, + 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, + 70, 111, 114, 119, 97, 114, 100, 72, 0, 82, 7, 102, 111, 114, 119, 97, 114, 100, 18, 70, + 10, 12, 115, 105, 100, 101, 95, 101, 102, 102, 101, 99, 116, 115, 24, 4, 32, 3, 40, 11, + 50, 35, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, + 114, 111, 116, 111, 99, 111, 108, 46, 83, 105, 100, 101, 69, 102, 102, 101, 99, 116, 82, + 11, 115, 105, 100, 101, 69, 102, 102, 101, 99, 116, 115, 66, 10, 10, 8, 114, 101, 115, + 112, 111, 110, 115, 101>> + ) + end + + oneof :response, 0 + field :failure, 1, type: Eigr.Functions.Protocol.Failure, oneof: 0 + field :reply, 2, type: Eigr.Functions.Protocol.Reply, oneof: 0 + field :forward, 3, type: Eigr.Functions.Protocol.Forward, oneof: 0 + field :side_effects, 4, repeated: true, type: Eigr.Functions.Protocol.SideEffect +end + +defmodule Eigr.Functions.Protocol.Action.ActionProtocol.Service do + @moduledoc false + use GRPC.Service, name: "eigr.functions.protocol.action.ActionProtocol" + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.ServiceDescriptorProto.decode( + <<10, 14, 65, 99, 116, 105, 111, 110, 80, 114, 111, 116, 111, 99, 111, 108, 18, 117, 10, 11, + 104, 97, 110, 100, 108, 101, 85, 110, 97, 114, 121, 18, 45, 46, 101, 105, 103, 114, 46, + 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, + 97, 99, 116, 105, 111, 110, 46, 65, 99, 116, 105, 111, 110, 67, 111, 109, 109, 97, 110, + 100, 26, 46, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, + 112, 114, 111, 116, 111, 99, 111, 108, 46, 97, 99, 116, 105, 111, 110, 46, 65, 99, 116, + 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 3, 136, 2, 0, 40, 0, 48, 0, 18, + 122, 10, 16, 104, 97, 110, 100, 108, 101, 83, 116, 114, 101, 97, 109, 101, 100, 73, 110, + 18, 45, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, + 114, 111, 116, 111, 99, 111, 108, 46, 97, 99, 116, 105, 111, 110, 46, 65, 99, 116, 105, + 111, 110, 67, 111, 109, 109, 97, 110, 100, 26, 46, 46, 101, 105, 103, 114, 46, 102, 117, + 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 97, 99, + 116, 105, 111, 110, 46, 65, 99, 116, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, + 34, 3, 136, 2, 0, 40, 1, 48, 0, 18, 123, 10, 17, 104, 97, 110, 100, 108, 101, 83, 116, + 114, 101, 97, 109, 101, 100, 79, 117, 116, 18, 45, 46, 101, 105, 103, 114, 46, 102, 117, + 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 97, 99, + 116, 105, 111, 110, 46, 65, 99, 116, 105, 111, 110, 67, 111, 109, 109, 97, 110, 100, 26, + 46, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, + 111, 116, 111, 99, 111, 108, 46, 97, 99, 116, 105, 111, 110, 46, 65, 99, 116, 105, 111, + 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 3, 136, 2, 0, 40, 0, 48, 1, 18, 120, 10, + 14, 104, 97, 110, 100, 108, 101, 83, 116, 114, 101, 97, 109, 101, 100, 18, 45, 46, 101, + 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, + 111, 99, 111, 108, 46, 97, 99, 116, 105, 111, 110, 46, 65, 99, 116, 105, 111, 110, 67, + 111, 109, 109, 97, 110, 100, 26, 46, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, + 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 97, 99, 116, 105, 111, + 110, 46, 65, 99, 116, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 3, 136, 2, + 0, 40, 1, 48, 1>> + ) + end + + rpc :handleUnary, + Eigr.Functions.Protocol.Action.ActionCommand, + Eigr.Functions.Protocol.Action.ActionResponse + + rpc :handleStreamedIn, + stream(Eigr.Functions.Protocol.Action.ActionCommand), + Eigr.Functions.Protocol.Action.ActionResponse + + rpc :handleStreamedOut, + Eigr.Functions.Protocol.Action.ActionCommand, + stream(Eigr.Functions.Protocol.Action.ActionResponse) + + rpc :handleStreamed, + stream(Eigr.Functions.Protocol.Action.ActionCommand), + stream(Eigr.Functions.Protocol.Action.ActionResponse) +end + +defmodule Eigr.Functions.Protocol.Action.ActionProtocol.Stub do + @moduledoc false + use GRPC.Stub, service: Eigr.Functions.Protocol.Action.ActionProtocol.Service +end diff --git a/apps/eigr_protocol/lib/eigr/functions/protocol/entity.pb.ex b/apps/eigr_protocol/lib/eigr/functions/protocol/entity.pb.ex new file mode 100644 index 0000000..fc762f3 --- /dev/null +++ b/apps/eigr_protocol/lib/eigr/functions/protocol/entity.pb.ex @@ -0,0 +1,537 @@ +defmodule Eigr.Functions.Protocol.Metadata do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + entries: [Eigr.Functions.Protocol.MetadataEntry.t()] + } + defstruct [:entries] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 8, 77, 101, 116, 97, 100, 97, 116, 97, 18, 64, 10, 7, 101, 110, 116, 114, 105, 101, + 115, 24, 1, 32, 3, 40, 11, 50, 38, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, + 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 77, 101, 116, 97, 100, + 97, 116, 97, 69, 110, 116, 114, 121, 82, 7, 101, 110, 116, 114, 105, 101, 115>> + ) + end + + field :entries, 1, repeated: true, type: Eigr.Functions.Protocol.MetadataEntry +end + +defmodule Eigr.Functions.Protocol.MetadataEntry do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + value: {atom, any}, + key: String.t() + } + defstruct [:value, :key] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 13, 77, 101, 116, 97, 100, 97, 116, 97, 69, 110, 116, 114, 121, 18, 16, 10, 3, 107, + 101, 121, 24, 1, 32, 1, 40, 9, 82, 3, 107, 101, 121, 18, 35, 10, 12, 115, 116, 114, 105, + 110, 103, 95, 118, 97, 108, 117, 101, 24, 2, 32, 1, 40, 9, 72, 0, 82, 11, 115, 116, 114, + 105, 110, 103, 86, 97, 108, 117, 101, 18, 33, 10, 11, 98, 121, 116, 101, 115, 95, 118, 97, + 108, 117, 101, 24, 3, 32, 1, 40, 12, 72, 0, 82, 10, 98, 121, 116, 101, 115, 86, 97, 108, + 117, 101, 66, 7, 10, 5, 118, 97, 108, 117, 101>> + ) + end + + oneof :value, 0 + field :key, 1, type: :string + field :string_value, 2, type: :string, oneof: 0 + field :bytes_value, 3, type: :bytes, oneof: 0 +end + +defmodule Eigr.Functions.Protocol.Reply do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + payload: Google.Protobuf.Any.t() | nil, + metadata: Eigr.Functions.Protocol.Metadata.t() | nil + } + defstruct [:payload, :metadata] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 5, 82, 101, 112, 108, 121, 18, 46, 10, 7, 112, 97, 121, 108, 111, 97, 100, 24, 1, 32, + 1, 40, 11, 50, 20, 46, 103, 111, 111, 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, + 102, 46, 65, 110, 121, 82, 7, 112, 97, 121, 108, 111, 97, 100, 18, 61, 10, 8, 109, 101, + 116, 97, 100, 97, 116, 97, 24, 2, 32, 1, 40, 11, 50, 33, 46, 101, 105, 103, 114, 46, 102, + 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 77, + 101, 116, 97, 100, 97, 116, 97, 82, 8, 109, 101, 116, 97, 100, 97, 116, 97>> + ) + end + + field :payload, 1, type: Google.Protobuf.Any + field :metadata, 2, type: Eigr.Functions.Protocol.Metadata +end + +defmodule Eigr.Functions.Protocol.Forward do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + service_name: String.t(), + command_name: String.t(), + payload: Google.Protobuf.Any.t() | nil, + metadata: Eigr.Functions.Protocol.Metadata.t() | nil + } + defstruct [:service_name, :command_name, :payload, :metadata] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 7, 70, 111, 114, 119, 97, 114, 100, 18, 33, 10, 12, 115, 101, 114, 118, 105, 99, 101, + 95, 110, 97, 109, 101, 24, 1, 32, 1, 40, 9, 82, 11, 115, 101, 114, 118, 105, 99, 101, 78, + 97, 109, 101, 18, 33, 10, 12, 99, 111, 109, 109, 97, 110, 100, 95, 110, 97, 109, 101, 24, + 2, 32, 1, 40, 9, 82, 11, 99, 111, 109, 109, 97, 110, 100, 78, 97, 109, 101, 18, 46, 10, 7, + 112, 97, 121, 108, 111, 97, 100, 24, 3, 32, 1, 40, 11, 50, 20, 46, 103, 111, 111, 103, + 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 65, 110, 121, 82, 7, 112, 97, + 121, 108, 111, 97, 100, 18, 61, 10, 8, 109, 101, 116, 97, 100, 97, 116, 97, 24, 4, 32, 1, + 40, 11, 50, 33, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, + 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 77, 101, 116, 97, 100, 97, 116, 97, 82, 8, + 109, 101, 116, 97, 100, 97, 116, 97>> + ) + end + + field :service_name, 1, type: :string + field :command_name, 2, type: :string + field :payload, 3, type: Google.Protobuf.Any + field :metadata, 4, type: Eigr.Functions.Protocol.Metadata +end + +defmodule Eigr.Functions.Protocol.ClientAction do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + action: {atom, any} + } + defstruct [:action] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 12, 67, 108, 105, 101, 110, 116, 65, 99, 116, 105, 111, 110, 18, 54, 10, 5, 114, 101, + 112, 108, 121, 24, 1, 32, 1, 40, 11, 50, 30, 46, 101, 105, 103, 114, 46, 102, 117, 110, + 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 82, 101, 112, + 108, 121, 72, 0, 82, 5, 114, 101, 112, 108, 121, 18, 60, 10, 7, 102, 111, 114, 119, 97, + 114, 100, 24, 2, 32, 1, 40, 11, 50, 32, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, + 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 70, 111, 114, 119, + 97, 114, 100, 72, 0, 82, 7, 102, 111, 114, 119, 97, 114, 100, 18, 60, 10, 7, 102, 97, 105, + 108, 117, 114, 101, 24, 3, 32, 1, 40, 11, 50, 32, 46, 101, 105, 103, 114, 46, 102, 117, + 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 70, 97, + 105, 108, 117, 114, 101, 72, 0, 82, 7, 102, 97, 105, 108, 117, 114, 101, 66, 8, 10, 6, 97, + 99, 116, 105, 111, 110>> + ) + end + + oneof :action, 0 + field :reply, 1, type: Eigr.Functions.Protocol.Reply, oneof: 0 + field :forward, 2, type: Eigr.Functions.Protocol.Forward, oneof: 0 + field :failure, 3, type: Eigr.Functions.Protocol.Failure, oneof: 0 +end + +defmodule Eigr.Functions.Protocol.SideEffect do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + service_name: String.t(), + command_name: String.t(), + payload: Google.Protobuf.Any.t() | nil, + synchronous: boolean, + broadcast: boolean, + metadata: Eigr.Functions.Protocol.Metadata.t() | nil + } + defstruct [:service_name, :command_name, :payload, :synchronous, :broadcast, :metadata] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 10, 83, 105, 100, 101, 69, 102, 102, 101, 99, 116, 18, 33, 10, 12, 115, 101, 114, 118, + 105, 99, 101, 95, 110, 97, 109, 101, 24, 1, 32, 1, 40, 9, 82, 11, 115, 101, 114, 118, 105, + 99, 101, 78, 97, 109, 101, 18, 33, 10, 12, 99, 111, 109, 109, 97, 110, 100, 95, 110, 97, + 109, 101, 24, 2, 32, 1, 40, 9, 82, 11, 99, 111, 109, 109, 97, 110, 100, 78, 97, 109, 101, + 18, 46, 10, 7, 112, 97, 121, 108, 111, 97, 100, 24, 3, 32, 1, 40, 11, 50, 20, 46, 103, + 111, 111, 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 65, 110, 121, 82, + 7, 112, 97, 121, 108, 111, 97, 100, 18, 32, 10, 11, 115, 121, 110, 99, 104, 114, 111, 110, + 111, 117, 115, 24, 4, 32, 1, 40, 8, 82, 11, 115, 121, 110, 99, 104, 114, 111, 110, 111, + 117, 115, 18, 28, 10, 9, 98, 114, 111, 97, 100, 99, 97, 115, 116, 24, 6, 32, 1, 40, 8, 82, + 9, 98, 114, 111, 97, 100, 99, 97, 115, 116, 18, 61, 10, 8, 109, 101, 116, 97, 100, 97, + 116, 97, 24, 5, 32, 1, 40, 11, 50, 33, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, + 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 77, 101, 116, 97, 100, + 97, 116, 97, 82, 8, 109, 101, 116, 97, 100, 97, 116, 97>> + ) + end + + field :service_name, 1, type: :string + field :command_name, 2, type: :string + field :payload, 3, type: Google.Protobuf.Any + field :synchronous, 4, type: :bool + field :broadcast, 6, type: :bool + field :metadata, 5, type: Eigr.Functions.Protocol.Metadata +end + +defmodule Eigr.Functions.Protocol.Command do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + entity_id: String.t(), + id: integer, + name: String.t(), + payload: Google.Protobuf.Any.t() | nil, + streamed: boolean, + metadata: Eigr.Functions.Protocol.Metadata.t() | nil + } + defstruct [:entity_id, :id, :name, :payload, :streamed, :metadata] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 7, 67, 111, 109, 109, 97, 110, 100, 18, 27, 10, 9, 101, 110, 116, 105, 116, 121, 95, + 105, 100, 24, 1, 32, 1, 40, 9, 82, 8, 101, 110, 116, 105, 116, 121, 73, 100, 18, 14, 10, + 2, 105, 100, 24, 2, 32, 1, 40, 3, 82, 2, 105, 100, 18, 18, 10, 4, 110, 97, 109, 101, 24, + 3, 32, 1, 40, 9, 82, 4, 110, 97, 109, 101, 18, 46, 10, 7, 112, 97, 121, 108, 111, 97, 100, + 24, 4, 32, 1, 40, 11, 50, 20, 46, 103, 111, 111, 103, 108, 101, 46, 112, 114, 111, 116, + 111, 98, 117, 102, 46, 65, 110, 121, 82, 7, 112, 97, 121, 108, 111, 97, 100, 18, 26, 10, + 8, 115, 116, 114, 101, 97, 109, 101, 100, 24, 5, 32, 1, 40, 8, 82, 8, 115, 116, 114, 101, + 97, 109, 101, 100, 18, 61, 10, 8, 109, 101, 116, 97, 100, 97, 116, 97, 24, 6, 32, 1, 40, + 11, 50, 33, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, + 112, 114, 111, 116, 111, 99, 111, 108, 46, 77, 101, 116, 97, 100, 97, 116, 97, 82, 8, 109, + 101, 116, 97, 100, 97, 116, 97>> + ) + end + + field :entity_id, 1, type: :string + field :id, 2, type: :int64 + field :name, 3, type: :string + field :payload, 4, type: Google.Protobuf.Any + field :streamed, 5, type: :bool + field :metadata, 6, type: Eigr.Functions.Protocol.Metadata +end + +defmodule Eigr.Functions.Protocol.StreamCancelled do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + entity_id: String.t(), + id: integer + } + defstruct [:entity_id, :id] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 15, 83, 116, 114, 101, 97, 109, 67, 97, 110, 99, 101, 108, 108, 101, 100, 18, 27, 10, + 9, 101, 110, 116, 105, 116, 121, 95, 105, 100, 24, 1, 32, 1, 40, 9, 82, 8, 101, 110, 116, + 105, 116, 121, 73, 100, 18, 14, 10, 2, 105, 100, 24, 2, 32, 1, 40, 3, 82, 2, 105, 100>> + ) + end + + field :entity_id, 1, type: :string + field :id, 2, type: :int64 +end + +defmodule Eigr.Functions.Protocol.Failure do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + command_id: integer, + description: String.t(), + restart: boolean + } + defstruct [:command_id, :description, :restart] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 7, 70, 97, 105, 108, 117, 114, 101, 18, 29, 10, 10, 99, 111, 109, 109, 97, 110, 100, + 95, 105, 100, 24, 1, 32, 1, 40, 3, 82, 9, 99, 111, 109, 109, 97, 110, 100, 73, 100, 18, + 32, 10, 11, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 24, 2, 32, 1, 40, 9, 82, + 11, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 18, 24, 10, 7, 114, 101, 115, + 116, 97, 114, 116, 24, 3, 32, 1, 40, 8, 82, 7, 114, 101, 115, 116, 97, 114, 116>> + ) + end + + field :command_id, 1, type: :int64 + field :description, 2, type: :string + field :restart, 3, type: :bool +end + +defmodule Eigr.Functions.Protocol.EntitySpec do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + proto: binary, + entities: [Eigr.Functions.Protocol.Entity.t()], + service_info: Eigr.Functions.Protocol.ServiceInfo.t() | nil + } + defstruct [:proto, :entities, :service_info] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 10, 69, 110, 116, 105, 116, 121, 83, 112, 101, 99, 18, 20, 10, 5, 112, 114, 111, 116, + 111, 24, 1, 32, 1, 40, 12, 82, 5, 112, 114, 111, 116, 111, 18, 59, 10, 8, 101, 110, 116, + 105, 116, 105, 101, 115, 24, 2, 32, 3, 40, 11, 50, 31, 46, 101, 105, 103, 114, 46, 102, + 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 69, + 110, 116, 105, 116, 121, 82, 8, 101, 110, 116, 105, 116, 105, 101, 115, 18, 71, 10, 12, + 115, 101, 114, 118, 105, 99, 101, 95, 105, 110, 102, 111, 24, 3, 32, 1, 40, 11, 50, 36, + 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, + 116, 111, 99, 111, 108, 46, 83, 101, 114, 118, 105, 99, 101, 73, 110, 102, 111, 82, 11, + 115, 101, 114, 118, 105, 99, 101, 73, 110, 102, 111>> + ) + end + + field :proto, 1, type: :bytes + field :entities, 2, repeated: true, type: Eigr.Functions.Protocol.Entity + field :service_info, 3, type: Eigr.Functions.Protocol.ServiceInfo +end + +defmodule Eigr.Functions.Protocol.ServiceInfo do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + service_name: String.t(), + service_version: String.t(), + service_runtime: String.t(), + support_library_name: String.t(), + support_library_version: String.t(), + protocol_major_version: integer, + protocol_minor_version: integer + } + defstruct [ + :service_name, + :service_version, + :service_runtime, + :support_library_name, + :support_library_version, + :protocol_major_version, + :protocol_minor_version + ] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 11, 83, 101, 114, 118, 105, 99, 101, 73, 110, 102, 111, 18, 33, 10, 12, 115, 101, 114, + 118, 105, 99, 101, 95, 110, 97, 109, 101, 24, 1, 32, 1, 40, 9, 82, 11, 115, 101, 114, 118, + 105, 99, 101, 78, 97, 109, 101, 18, 39, 10, 15, 115, 101, 114, 118, 105, 99, 101, 95, 118, + 101, 114, 115, 105, 111, 110, 24, 2, 32, 1, 40, 9, 82, 14, 115, 101, 114, 118, 105, 99, + 101, 86, 101, 114, 115, 105, 111, 110, 18, 39, 10, 15, 115, 101, 114, 118, 105, 99, 101, + 95, 114, 117, 110, 116, 105, 109, 101, 24, 3, 32, 1, 40, 9, 82, 14, 115, 101, 114, 118, + 105, 99, 101, 82, 117, 110, 116, 105, 109, 101, 18, 48, 10, 20, 115, 117, 112, 112, 111, + 114, 116, 95, 108, 105, 98, 114, 97, 114, 121, 95, 110, 97, 109, 101, 24, 4, 32, 1, 40, 9, + 82, 18, 115, 117, 112, 112, 111, 114, 116, 76, 105, 98, 114, 97, 114, 121, 78, 97, 109, + 101, 18, 54, 10, 23, 115, 117, 112, 112, 111, 114, 116, 95, 108, 105, 98, 114, 97, 114, + 121, 95, 118, 101, 114, 115, 105, 111, 110, 24, 5, 32, 1, 40, 9, 82, 21, 115, 117, 112, + 112, 111, 114, 116, 76, 105, 98, 114, 97, 114, 121, 86, 101, 114, 115, 105, 111, 110, 18, + 52, 10, 22, 112, 114, 111, 116, 111, 99, 111, 108, 95, 109, 97, 106, 111, 114, 95, 118, + 101, 114, 115, 105, 111, 110, 24, 6, 32, 1, 40, 5, 82, 20, 112, 114, 111, 116, 111, 99, + 111, 108, 77, 97, 106, 111, 114, 86, 101, 114, 115, 105, 111, 110, 18, 52, 10, 22, 112, + 114, 111, 116, 111, 99, 111, 108, 95, 109, 105, 110, 111, 114, 95, 118, 101, 114, 115, + 105, 111, 110, 24, 7, 32, 1, 40, 5, 82, 20, 112, 114, 111, 116, 111, 99, 111, 108, 77, + 105, 110, 111, 114, 86, 101, 114, 115, 105, 111, 110>> + ) + end + + field :service_name, 1, type: :string + field :service_version, 2, type: :string + field :service_runtime, 3, type: :string + field :support_library_name, 4, type: :string + field :support_library_version, 5, type: :string + field :protocol_major_version, 6, type: :int32 + field :protocol_minor_version, 7, type: :int32 +end + +defmodule Eigr.Functions.Protocol.Entity do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + entity_type: String.t(), + service_name: String.t(), + persistence_id: String.t(), + passivation_strategy: Eigr.Functions.Protocol.EntityPassivationStrategy.t() | nil + } + defstruct [:entity_type, :service_name, :persistence_id, :passivation_strategy] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 6, 69, 110, 116, 105, 116, 121, 18, 31, 10, 11, 101, 110, 116, 105, 116, 121, 95, 116, + 121, 112, 101, 24, 1, 32, 1, 40, 9, 82, 10, 101, 110, 116, 105, 116, 121, 84, 121, 112, + 101, 18, 33, 10, 12, 115, 101, 114, 118, 105, 99, 101, 95, 110, 97, 109, 101, 24, 2, 32, + 1, 40, 9, 82, 11, 115, 101, 114, 118, 105, 99, 101, 78, 97, 109, 101, 18, 37, 10, 14, 112, + 101, 114, 115, 105, 115, 116, 101, 110, 99, 101, 95, 105, 100, 24, 3, 32, 1, 40, 9, 82, + 13, 112, 101, 114, 115, 105, 115, 116, 101, 110, 99, 101, 73, 100, 18, 101, 10, 20, 112, + 97, 115, 115, 105, 118, 97, 116, 105, 111, 110, 95, 115, 116, 114, 97, 116, 101, 103, 121, + 24, 4, 32, 1, 40, 11, 50, 50, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, + 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 69, 110, 116, 105, 116, 121, + 80, 97, 115, 115, 105, 118, 97, 116, 105, 111, 110, 83, 116, 114, 97, 116, 101, 103, 121, + 82, 19, 112, 97, 115, 115, 105, 118, 97, 116, 105, 111, 110, 83, 116, 114, 97, 116, 101, + 103, 121>> + ) + end + + field :entity_type, 1, type: :string + field :service_name, 2, type: :string + field :persistence_id, 3, type: :string + field :passivation_strategy, 4, type: Eigr.Functions.Protocol.EntityPassivationStrategy +end + +defmodule Eigr.Functions.Protocol.EntityPassivationStrategy do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + strategy: {atom, any} + } + defstruct [:strategy] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 25, 69, 110, 116, 105, 116, 121, 80, 97, 115, 115, 105, 118, 97, 116, 105, 111, 110, + 83, 116, 114, 97, 116, 101, 103, 121, 18, 79, 10, 7, 116, 105, 109, 101, 111, 117, 116, + 24, 1, 32, 1, 40, 11, 50, 51, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, + 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 84, 105, 109, 101, 111, 117, + 116, 80, 97, 115, 115, 105, 118, 97, 116, 105, 111, 110, 83, 116, 114, 97, 116, 101, 103, + 121, 72, 0, 82, 7, 116, 105, 109, 101, 111, 117, 116, 66, 10, 10, 8, 115, 116, 114, 97, + 116, 101, 103, 121>> + ) + end + + oneof :strategy, 0 + field :timeout, 1, type: Eigr.Functions.Protocol.TimeoutPassivationStrategy, oneof: 0 +end + +defmodule Eigr.Functions.Protocol.TimeoutPassivationStrategy do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + timeout: integer + } + defstruct [:timeout] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 26, 84, 105, 109, 101, 111, 117, 116, 80, 97, 115, 115, 105, 118, 97, 116, 105, 111, + 110, 83, 116, 114, 97, 116, 101, 103, 121, 18, 24, 10, 7, 116, 105, 109, 101, 111, 117, + 116, 24, 1, 32, 1, 40, 3, 82, 7, 116, 105, 109, 101, 111, 117, 116>> + ) + end + + field :timeout, 1, type: :int64 +end + +defmodule Eigr.Functions.Protocol.UserFunctionError do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + message: String.t() + } + defstruct [:message] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 17, 85, 115, 101, 114, 70, 117, 110, 99, 116, 105, 111, 110, 69, 114, 114, 111, 114, + 18, 24, 10, 7, 109, 101, 115, 115, 97, 103, 101, 24, 1, 32, 1, 40, 9, 82, 7, 109, 101, + 115, 115, 97, 103, 101>> + ) + end + + field :message, 1, type: :string +end + +defmodule Eigr.Functions.Protocol.ProxyInfo do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + protocol_major_version: integer, + protocol_minor_version: integer, + proxy_name: String.t(), + proxy_version: String.t(), + supported_entity_types: [String.t()] + } + defstruct [ + :protocol_major_version, + :protocol_minor_version, + :proxy_name, + :proxy_version, + :supported_entity_types + ] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 9, 80, 114, 111, 120, 121, 73, 110, 102, 111, 18, 52, 10, 22, 112, 114, 111, 116, 111, + 99, 111, 108, 95, 109, 97, 106, 111, 114, 95, 118, 101, 114, 115, 105, 111, 110, 24, 1, + 32, 1, 40, 5, 82, 20, 112, 114, 111, 116, 111, 99, 111, 108, 77, 97, 106, 111, 114, 86, + 101, 114, 115, 105, 111, 110, 18, 52, 10, 22, 112, 114, 111, 116, 111, 99, 111, 108, 95, + 109, 105, 110, 111, 114, 95, 118, 101, 114, 115, 105, 111, 110, 24, 2, 32, 1, 40, 5, 82, + 20, 112, 114, 111, 116, 111, 99, 111, 108, 77, 105, 110, 111, 114, 86, 101, 114, 115, 105, + 111, 110, 18, 29, 10, 10, 112, 114, 111, 120, 121, 95, 110, 97, 109, 101, 24, 3, 32, 1, + 40, 9, 82, 9, 112, 114, 111, 120, 121, 78, 97, 109, 101, 18, 35, 10, 13, 112, 114, 111, + 120, 121, 95, 118, 101, 114, 115, 105, 111, 110, 24, 4, 32, 1, 40, 9, 82, 12, 112, 114, + 111, 120, 121, 86, 101, 114, 115, 105, 111, 110, 18, 52, 10, 22, 115, 117, 112, 112, 111, + 114, 116, 101, 100, 95, 101, 110, 116, 105, 116, 121, 95, 116, 121, 112, 101, 115, 24, 5, + 32, 3, 40, 9, 82, 20, 115, 117, 112, 112, 111, 114, 116, 101, 100, 69, 110, 116, 105, 116, + 121, 84, 121, 112, 101, 115>> + ) + end + + field :protocol_major_version, 1, type: :int32 + field :protocol_minor_version, 2, type: :int32 + field :proxy_name, 3, type: :string + field :proxy_version, 4, type: :string + field :supported_entity_types, 5, repeated: true, type: :string +end + +defmodule Eigr.Functions.Protocol.EntityDiscovery.Service do + @moduledoc false + use GRPC.Service, name: "eigr.functions.protocol.EntityDiscovery" + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.ServiceDescriptorProto.decode( + <<10, 15, 69, 110, 116, 105, 116, 121, 68, 105, 115, 99, 111, 118, 101, 114, 121, 18, 92, + 10, 8, 100, 105, 115, 99, 111, 118, 101, 114, 18, 34, 46, 101, 105, 103, 114, 46, 102, + 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 80, + 114, 111, 120, 121, 73, 110, 102, 111, 26, 35, 46, 101, 105, 103, 114, 46, 102, 117, 110, + 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 69, 110, 116, + 105, 116, 121, 83, 112, 101, 99, 34, 3, 136, 2, 0, 40, 0, 48, 0, 18, 90, 10, 11, 114, 101, + 112, 111, 114, 116, 69, 114, 114, 111, 114, 18, 42, 46, 101, 105, 103, 114, 46, 102, 117, + 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 85, 115, + 101, 114, 70, 117, 110, 99, 116, 105, 111, 110, 69, 114, 114, 111, 114, 26, 22, 46, 103, + 111, 111, 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 69, 109, 112, 116, + 121, 34, 3, 136, 2, 0, 40, 0, 48, 0>> + ) + end + + rpc :discover, Eigr.Functions.Protocol.ProxyInfo, Eigr.Functions.Protocol.EntitySpec + rpc :reportError, Eigr.Functions.Protocol.UserFunctionError, Google.Protobuf.Empty +end + +defmodule Eigr.Functions.Protocol.EntityDiscovery.Stub do + @moduledoc false + use GRPC.Stub, service: Eigr.Functions.Protocol.EntityDiscovery.Service +end diff --git a/apps/eigr_protocol/lib/eigr/functions/protocol/entity_key.pb.ex b/apps/eigr_protocol/lib/eigr/functions/protocol/entity_key.pb.ex new file mode 100644 index 0000000..e69de29 diff --git a/apps/eigr_protocol/lib/eigr/functions/protocol/event_sourced.pb.ex b/apps/eigr_protocol/lib/eigr/functions/protocol/event_sourced.pb.ex new file mode 100644 index 0000000..16b5636 --- /dev/null +++ b/apps/eigr_protocol/lib/eigr/functions/protocol/event_sourced.pb.ex @@ -0,0 +1,216 @@ +defmodule Eigr.Functions.Protocol.Eventsourced.EventSourcedInit do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + service_name: String.t(), + entity_id: String.t(), + snapshot: Eigr.Functions.Protocol.Eventsourced.EventSourcedSnapshot.t() | nil + } + defstruct [:service_name, :entity_id, :snapshot] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 16, 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 100, 73, 110, 105, 116, 18, + 33, 10, 12, 115, 101, 114, 118, 105, 99, 101, 95, 110, 97, 109, 101, 24, 1, 32, 1, 40, 9, + 82, 11, 115, 101, 114, 118, 105, 99, 101, 78, 97, 109, 101, 18, 27, 10, 9, 101, 110, 116, + 105, 116, 121, 95, 105, 100, 24, 2, 32, 1, 40, 9, 82, 8, 101, 110, 116, 105, 116, 121, 73, + 100, 18, 86, 10, 8, 115, 110, 97, 112, 115, 104, 111, 116, 24, 3, 32, 1, 40, 11, 50, 58, + 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, + 116, 111, 99, 111, 108, 46, 101, 118, 101, 110, 116, 115, 111, 117, 114, 99, 101, 100, 46, + 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 100, 83, 110, 97, 112, 115, 104, 111, + 116, 82, 8, 115, 110, 97, 112, 115, 104, 111, 116>> + ) + end + + field :service_name, 1, type: :string + field :entity_id, 2, type: :string + field :snapshot, 3, type: Eigr.Functions.Protocol.Eventsourced.EventSourcedSnapshot +end + +defmodule Eigr.Functions.Protocol.Eventsourced.EventSourcedSnapshot do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + snapshot_sequence: integer, + snapshot: Google.Protobuf.Any.t() | nil + } + defstruct [:snapshot_sequence, :snapshot] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 20, 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 100, 83, 110, 97, 112, 115, + 104, 111, 116, 18, 43, 10, 17, 115, 110, 97, 112, 115, 104, 111, 116, 95, 115, 101, 113, + 117, 101, 110, 99, 101, 24, 1, 32, 1, 40, 3, 82, 16, 115, 110, 97, 112, 115, 104, 111, + 116, 83, 101, 113, 117, 101, 110, 99, 101, 18, 48, 10, 8, 115, 110, 97, 112, 115, 104, + 111, 116, 24, 2, 32, 1, 40, 11, 50, 20, 46, 103, 111, 111, 103, 108, 101, 46, 112, 114, + 111, 116, 111, 98, 117, 102, 46, 65, 110, 121, 82, 8, 115, 110, 97, 112, 115, 104, 111, + 116>> + ) + end + + field :snapshot_sequence, 1, type: :int64 + field :snapshot, 2, type: Google.Protobuf.Any +end + +defmodule Eigr.Functions.Protocol.Eventsourced.EventSourcedEvent do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + sequence: integer, + payload: Google.Protobuf.Any.t() | nil + } + defstruct [:sequence, :payload] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 17, 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 100, 69, 118, 101, 110, 116, + 18, 26, 10, 8, 115, 101, 113, 117, 101, 110, 99, 101, 24, 1, 32, 1, 40, 3, 82, 8, 115, + 101, 113, 117, 101, 110, 99, 101, 18, 46, 10, 7, 112, 97, 121, 108, 111, 97, 100, 24, 2, + 32, 1, 40, 11, 50, 20, 46, 103, 111, 111, 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, + 117, 102, 46, 65, 110, 121, 82, 7, 112, 97, 121, 108, 111, 97, 100>> + ) + end + + field :sequence, 1, type: :int64 + field :payload, 2, type: Google.Protobuf.Any +end + +defmodule Eigr.Functions.Protocol.Eventsourced.EventSourcedReply do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + command_id: integer, + client_action: Eigr.Functions.Protocol.ClientAction.t() | nil, + side_effects: [Eigr.Functions.Protocol.SideEffect.t()], + events: [Google.Protobuf.Any.t()], + snapshot: Google.Protobuf.Any.t() | nil + } + defstruct [:command_id, :client_action, :side_effects, :events, :snapshot] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 17, 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 100, 82, 101, 112, 108, 121, + 18, 29, 10, 10, 99, 111, 109, 109, 97, 110, 100, 95, 105, 100, 24, 1, 32, 1, 40, 3, 82, 9, + 99, 111, 109, 109, 97, 110, 100, 73, 100, 18, 74, 10, 13, 99, 108, 105, 101, 110, 116, 95, + 97, 99, 116, 105, 111, 110, 24, 2, 32, 1, 40, 11, 50, 37, 46, 101, 105, 103, 114, 46, 102, + 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 67, + 108, 105, 101, 110, 116, 65, 99, 116, 105, 111, 110, 82, 12, 99, 108, 105, 101, 110, 116, + 65, 99, 116, 105, 111, 110, 18, 70, 10, 12, 115, 105, 100, 101, 95, 101, 102, 102, 101, + 99, 116, 115, 24, 3, 32, 3, 40, 11, 50, 35, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, + 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 83, 105, 100, 101, + 69, 102, 102, 101, 99, 116, 82, 11, 115, 105, 100, 101, 69, 102, 102, 101, 99, 116, 115, + 18, 44, 10, 6, 101, 118, 101, 110, 116, 115, 24, 4, 32, 3, 40, 11, 50, 20, 46, 103, 111, + 111, 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 65, 110, 121, 82, 6, + 101, 118, 101, 110, 116, 115, 18, 48, 10, 8, 115, 110, 97, 112, 115, 104, 111, 116, 24, 5, + 32, 1, 40, 11, 50, 20, 46, 103, 111, 111, 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, + 117, 102, 46, 65, 110, 121, 82, 8, 115, 110, 97, 112, 115, 104, 111, 116>> + ) + end + + field :command_id, 1, type: :int64 + field :client_action, 2, type: Eigr.Functions.Protocol.ClientAction + field :side_effects, 3, repeated: true, type: Eigr.Functions.Protocol.SideEffect + field :events, 4, repeated: true, type: Google.Protobuf.Any + field :snapshot, 5, type: Google.Protobuf.Any +end + +defmodule Eigr.Functions.Protocol.Eventsourced.EventSourcedStreamIn do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + message: {atom, any} + } + defstruct [:message] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 20, 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 100, 83, 116, 114, 101, 97, + 109, 73, 110, 18, 76, 10, 4, 105, 110, 105, 116, 24, 1, 32, 1, 40, 11, 50, 54, 46, 101, + 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, + 111, 99, 111, 108, 46, 101, 118, 101, 110, 116, 115, 111, 117, 114, 99, 101, 100, 46, 69, + 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 100, 73, 110, 105, 116, 72, 0, 82, 4, 105, + 110, 105, 116, 18, 79, 10, 5, 101, 118, 101, 110, 116, 24, 2, 32, 1, 40, 11, 50, 55, 46, + 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, + 116, 111, 99, 111, 108, 46, 101, 118, 101, 110, 116, 115, 111, 117, 114, 99, 101, 100, 46, + 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 100, 69, 118, 101, 110, 116, 72, 0, + 82, 5, 101, 118, 101, 110, 116, 18, 60, 10, 7, 99, 111, 109, 109, 97, 110, 100, 24, 3, 32, + 1, 40, 11, 50, 32, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, + 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 67, 111, 109, 109, 97, 110, 100, 72, 0, 82, + 7, 99, 111, 109, 109, 97, 110, 100, 66, 9, 10, 7, 109, 101, 115, 115, 97, 103, 101>> + ) + end + + oneof :message, 0 + field :init, 1, type: Eigr.Functions.Protocol.Eventsourced.EventSourcedInit, oneof: 0 + field :event, 2, type: Eigr.Functions.Protocol.Eventsourced.EventSourcedEvent, oneof: 0 + field :command, 3, type: Eigr.Functions.Protocol.Command, oneof: 0 +end + +defmodule Eigr.Functions.Protocol.Eventsourced.EventSourcedStreamOut do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + message: {atom, any} + } + defstruct [:message] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 21, 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 100, 83, 116, 114, 101, 97, + 109, 79, 117, 116, 18, 79, 10, 5, 114, 101, 112, 108, 121, 24, 1, 32, 1, 40, 11, 50, 55, + 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, + 116, 111, 99, 111, 108, 46, 101, 118, 101, 110, 116, 115, 111, 117, 114, 99, 101, 100, 46, + 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 100, 82, 101, 112, 108, 121, 72, 0, + 82, 5, 114, 101, 112, 108, 121, 18, 60, 10, 7, 102, 97, 105, 108, 117, 114, 101, 24, 2, + 32, 1, 40, 11, 50, 32, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, + 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 70, 97, 105, 108, 117, 114, 101, 72, + 0, 82, 7, 102, 97, 105, 108, 117, 114, 101, 66, 9, 10, 7, 109, 101, 115, 115, 97, 103, + 101>> + ) + end + + oneof :message, 0 + field :reply, 1, type: Eigr.Functions.Protocol.Eventsourced.EventSourcedReply, oneof: 0 + field :failure, 2, type: Eigr.Functions.Protocol.Failure, oneof: 0 +end + +defmodule Eigr.Functions.Protocol.Eventsourced.EventSourced.Service do + @moduledoc false + use GRPC.Service, name: "eigr.functions.protocol.eventsourced.EventSourced" + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.ServiceDescriptorProto.decode( + <<10, 12, 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 100, 18, 138, 1, 10, 6, 104, + 97, 110, 100, 108, 101, 18, 58, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, + 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 101, 118, 101, 110, 116, + 115, 111, 117, 114, 99, 101, 100, 46, 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, + 100, 83, 116, 114, 101, 97, 109, 73, 110, 26, 59, 46, 101, 105, 103, 114, 46, 102, 117, + 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 101, 118, + 101, 110, 116, 115, 111, 117, 114, 99, 101, 100, 46, 69, 118, 101, 110, 116, 83, 111, 117, + 114, 99, 101, 100, 83, 116, 114, 101, 97, 109, 79, 117, 116, 34, 3, 136, 2, 0, 40, 1, 48, + 1>> + ) + end + + rpc :handle, + stream(Eigr.Functions.Protocol.Eventsourced.EventSourcedStreamIn), + stream(Eigr.Functions.Protocol.Eventsourced.EventSourcedStreamOut) +end + +defmodule Eigr.Functions.Protocol.Eventsourced.EventSourced.Stub do + @moduledoc false + use GRPC.Stub, service: Eigr.Functions.Protocol.Eventsourced.EventSourced.Service +end diff --git a/apps/eigr_protocol/lib/eigr/functions/protocol/eventing.pb.ex b/apps/eigr_protocol/lib/eigr/functions/protocol/eventing.pb.ex new file mode 100644 index 0000000..1aaf1a9 --- /dev/null +++ b/apps/eigr_protocol/lib/eigr/functions/protocol/eventing.pb.ex @@ -0,0 +1,77 @@ +defmodule Eigr.Functions.Protocol.Eventing.Eventing do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + in: Eigr.Functions.Protocol.Eventing.EventSource.t() | nil, + out: Eigr.Functions.Protocol.Eventing.EventDestination.t() | nil + } + defstruct [:in, :out] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 8, 69, 118, 101, 110, 116, 105, 110, 103, 18, 61, 10, 2, 105, 110, 24, 1, 32, 1, 40, + 11, 50, 45, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, + 112, 114, 111, 116, 111, 99, 111, 108, 46, 101, 118, 101, 110, 116, 105, 110, 103, 46, 69, + 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 82, 2, 105, 110, 18, 68, 10, 3, 111, 117, + 116, 24, 2, 32, 1, 40, 11, 50, 50, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, + 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 101, 118, 101, 110, + 116, 105, 110, 103, 46, 69, 118, 101, 110, 116, 68, 101, 115, 116, 105, 110, 97, 116, 105, + 111, 110, 82, 3, 111, 117, 116>> + ) + end + + field :in, 1, type: Eigr.Functions.Protocol.Eventing.EventSource + field :out, 2, type: Eigr.Functions.Protocol.Eventing.EventDestination +end + +defmodule Eigr.Functions.Protocol.Eventing.EventSource do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + source: {atom, any}, + consumer_group: String.t() + } + defstruct [:source, :consumer_group] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 11, 69, 118, 101, 110, 116, 83, 111, 117, 114, 99, 101, 18, 37, 10, 14, 99, 111, 110, + 115, 117, 109, 101, 114, 95, 103, 114, 111, 117, 112, 24, 1, 32, 1, 40, 9, 82, 13, 99, + 111, 110, 115, 117, 109, 101, 114, 71, 114, 111, 117, 112, 18, 22, 10, 5, 116, 111, 112, + 105, 99, 24, 2, 32, 1, 40, 9, 72, 0, 82, 5, 116, 111, 112, 105, 99, 18, 29, 10, 9, 101, + 118, 101, 110, 116, 95, 108, 111, 103, 24, 3, 32, 1, 40, 9, 72, 0, 82, 8, 101, 118, 101, + 110, 116, 76, 111, 103, 66, 8, 10, 6, 115, 111, 117, 114, 99, 101>> + ) + end + + oneof :source, 0 + field :consumer_group, 1, type: :string + field :topic, 2, type: :string, oneof: 0 + field :event_log, 3, type: :string, oneof: 0 +end + +defmodule Eigr.Functions.Protocol.Eventing.EventDestination do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + destination: {atom, any} + } + defstruct [:destination] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 16, 69, 118, 101, 110, 116, 68, 101, 115, 116, 105, 110, 97, 116, 105, 111, 110, 18, + 22, 10, 5, 116, 111, 112, 105, 99, 24, 1, 32, 1, 40, 9, 72, 0, 82, 5, 116, 111, 112, 105, + 99, 66, 13, 10, 11, 100, 101, 115, 116, 105, 110, 97, 116, 105, 111, 110>> + ) + end + + oneof :destination, 0 + field :topic, 1, type: :string, oneof: 0 +end diff --git a/apps/eigr_protocol/lib/eigr/functions/protocol/value_entity.pb.ex b/apps/eigr_protocol/lib/eigr/functions/protocol/value_entity.pb.ex new file mode 100644 index 0000000..3d2cf8c --- /dev/null +++ b/apps/eigr_protocol/lib/eigr/functions/protocol/value_entity.pb.ex @@ -0,0 +1,244 @@ +defmodule Eigr.Functions.Protocol.Valueentity.ValueEntityStreamIn do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + message: {atom, any} + } + defstruct [:message] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 19, 86, 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 83, 116, 114, 101, 97, 109, + 73, 110, 18, 74, 10, 4, 105, 110, 105, 116, 24, 1, 32, 1, 40, 11, 50, 52, 46, 101, 105, + 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, + 111, 108, 46, 118, 97, 108, 117, 101, 101, 110, 116, 105, 116, 121, 46, 86, 97, 108, 117, + 101, 69, 110, 116, 105, 116, 121, 73, 110, 105, 116, 72, 0, 82, 4, 105, 110, 105, 116, 18, + 60, 10, 7, 99, 111, 109, 109, 97, 110, 100, 24, 2, 32, 1, 40, 11, 50, 32, 46, 101, 105, + 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, + 111, 108, 46, 67, 111, 109, 109, 97, 110, 100, 72, 0, 82, 7, 99, 111, 109, 109, 97, 110, + 100, 66, 9, 10, 7, 109, 101, 115, 115, 97, 103, 101>> + ) + end + + oneof :message, 0 + field :init, 1, type: Eigr.Functions.Protocol.Valueentity.ValueEntityInit, oneof: 0 + field :command, 2, type: Eigr.Functions.Protocol.Command, oneof: 0 +end + +defmodule Eigr.Functions.Protocol.Valueentity.ValueEntityInit do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + service_name: String.t(), + entity_id: String.t(), + state: Eigr.Functions.Protocol.Valueentity.ValueEntityInitState.t() | nil + } + defstruct [:service_name, :entity_id, :state] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 15, 86, 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 73, 110, 105, 116, 18, 33, 10, + 12, 115, 101, 114, 118, 105, 99, 101, 95, 110, 97, 109, 101, 24, 1, 32, 1, 40, 9, 82, 11, + 115, 101, 114, 118, 105, 99, 101, 78, 97, 109, 101, 18, 27, 10, 9, 101, 110, 116, 105, + 116, 121, 95, 105, 100, 24, 2, 32, 1, 40, 9, 82, 8, 101, 110, 116, 105, 116, 121, 73, 100, + 18, 79, 10, 5, 115, 116, 97, 116, 101, 24, 3, 32, 1, 40, 11, 50, 57, 46, 101, 105, 103, + 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, + 108, 46, 118, 97, 108, 117, 101, 101, 110, 116, 105, 116, 121, 46, 86, 97, 108, 117, 101, + 69, 110, 116, 105, 116, 121, 73, 110, 105, 116, 83, 116, 97, 116, 101, 82, 5, 115, 116, + 97, 116, 101>> + ) + end + + field :service_name, 1, type: :string + field :entity_id, 2, type: :string + field :state, 3, type: Eigr.Functions.Protocol.Valueentity.ValueEntityInitState +end + +defmodule Eigr.Functions.Protocol.Valueentity.ValueEntityInitState do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + value: Google.Protobuf.Any.t() | nil + } + defstruct [:value] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 20, 86, 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 73, 110, 105, 116, 83, 116, + 97, 116, 101, 18, 42, 10, 5, 118, 97, 108, 117, 101, 24, 1, 32, 1, 40, 11, 50, 20, 46, + 103, 111, 111, 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 65, 110, 121, + 82, 5, 118, 97, 108, 117, 101>> + ) + end + + field :value, 1, type: Google.Protobuf.Any +end + +defmodule Eigr.Functions.Protocol.Valueentity.ValueEntityStreamOut do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + message: {atom, any} + } + defstruct [:message] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 20, 86, 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 83, 116, 114, 101, 97, 109, + 79, 117, 116, 18, 77, 10, 5, 114, 101, 112, 108, 121, 24, 1, 32, 1, 40, 11, 50, 53, 46, + 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, + 116, 111, 99, 111, 108, 46, 118, 97, 108, 117, 101, 101, 110, 116, 105, 116, 121, 46, 86, + 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 82, 101, 112, 108, 121, 72, 0, 82, 5, 114, + 101, 112, 108, 121, 18, 60, 10, 7, 102, 97, 105, 108, 117, 114, 101, 24, 2, 32, 1, 40, 11, + 50, 32, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, + 114, 111, 116, 111, 99, 111, 108, 46, 70, 97, 105, 108, 117, 114, 101, 72, 0, 82, 7, 102, + 97, 105, 108, 117, 114, 101, 66, 9, 10, 7, 109, 101, 115, 115, 97, 103, 101>> + ) + end + + oneof :message, 0 + field :reply, 1, type: Eigr.Functions.Protocol.Valueentity.ValueEntityReply, oneof: 0 + field :failure, 2, type: Eigr.Functions.Protocol.Failure, oneof: 0 +end + +defmodule Eigr.Functions.Protocol.Valueentity.ValueEntityReply do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + command_id: integer, + client_action: Eigr.Functions.Protocol.ClientAction.t() | nil, + side_effects: [Eigr.Functions.Protocol.SideEffect.t()], + state_action: Eigr.Functions.Protocol.Valueentity.ValueEntityAction.t() | nil + } + defstruct [:command_id, :client_action, :side_effects, :state_action] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 16, 86, 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 82, 101, 112, 108, 121, 18, + 29, 10, 10, 99, 111, 109, 109, 97, 110, 100, 95, 105, 100, 24, 1, 32, 1, 40, 3, 82, 9, 99, + 111, 109, 109, 97, 110, 100, 73, 100, 18, 74, 10, 13, 99, 108, 105, 101, 110, 116, 95, 97, + 99, 116, 105, 111, 110, 24, 2, 32, 1, 40, 11, 50, 37, 46, 101, 105, 103, 114, 46, 102, + 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 67, + 108, 105, 101, 110, 116, 65, 99, 116, 105, 111, 110, 82, 12, 99, 108, 105, 101, 110, 116, + 65, 99, 116, 105, 111, 110, 18, 70, 10, 12, 115, 105, 100, 101, 95, 101, 102, 102, 101, + 99, 116, 115, 24, 3, 32, 3, 40, 11, 50, 35, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, + 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 83, 105, 100, 101, + 69, 102, 102, 101, 99, 116, 82, 11, 115, 105, 100, 101, 69, 102, 102, 101, 99, 116, 115, + 18, 89, 10, 12, 115, 116, 97, 116, 101, 95, 97, 99, 116, 105, 111, 110, 24, 4, 32, 1, 40, + 11, 50, 54, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, + 112, 114, 111, 116, 111, 99, 111, 108, 46, 118, 97, 108, 117, 101, 101, 110, 116, 105, + 116, 121, 46, 86, 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 65, 99, 116, 105, 111, + 110, 82, 11, 115, 116, 97, 116, 101, 65, 99, 116, 105, 111, 110>> + ) + end + + field :command_id, 1, type: :int64 + field :client_action, 2, type: Eigr.Functions.Protocol.ClientAction + field :side_effects, 3, repeated: true, type: Eigr.Functions.Protocol.SideEffect + field :state_action, 4, type: Eigr.Functions.Protocol.Valueentity.ValueEntityAction +end + +defmodule Eigr.Functions.Protocol.Valueentity.ValueEntityAction do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + action: {atom, any} + } + defstruct [:action] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 17, 86, 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 65, 99, 116, 105, 111, 110, + 18, 80, 10, 6, 117, 112, 100, 97, 116, 101, 24, 1, 32, 1, 40, 11, 50, 54, 46, 101, 105, + 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, + 111, 108, 46, 118, 97, 108, 117, 101, 101, 110, 116, 105, 116, 121, 46, 86, 97, 108, 117, + 101, 69, 110, 116, 105, 116, 121, 85, 112, 100, 97, 116, 101, 72, 0, 82, 6, 117, 112, 100, + 97, 116, 101, 18, 80, 10, 6, 100, 101, 108, 101, 116, 101, 24, 2, 32, 1, 40, 11, 50, 54, + 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, 110, 115, 46, 112, 114, 111, + 116, 111, 99, 111, 108, 46, 118, 97, 108, 117, 101, 101, 110, 116, 105, 116, 121, 46, 86, + 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 68, 101, 108, 101, 116, 101, 72, 0, 82, 6, + 100, 101, 108, 101, 116, 101, 66, 8, 10, 6, 97, 99, 116, 105, 111, 110>> + ) + end + + oneof :action, 0 + field :update, 1, type: Eigr.Functions.Protocol.Valueentity.ValueEntityUpdate, oneof: 0 + field :delete, 2, type: Eigr.Functions.Protocol.Valueentity.ValueEntityDelete, oneof: 0 +end + +defmodule Eigr.Functions.Protocol.Valueentity.ValueEntityUpdate do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + value: Google.Protobuf.Any.t() | nil + } + defstruct [:value] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 17, 86, 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 85, 112, 100, 97, 116, 101, + 18, 42, 10, 5, 118, 97, 108, 117, 101, 24, 1, 32, 1, 40, 11, 50, 20, 46, 103, 111, 111, + 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 65, 110, 121, 82, 5, 118, + 97, 108, 117, 101>> + ) + end + + field :value, 1, type: Google.Protobuf.Any +end + +defmodule Eigr.Functions.Protocol.Valueentity.ValueEntityDelete do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{} + defstruct [] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 17, 86, 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 68, 101, 108, 101, 116, 101>> + ) + end +end + +defmodule Eigr.Functions.Protocol.Valueentity.ValueEntity.Service do + @moduledoc false + use GRPC.Service, name: "eigr.functions.protocol.valueentity.ValueEntity" + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.ServiceDescriptorProto.decode( + <<10, 11, 86, 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 18, 134, 1, 10, 6, 104, 97, + 110, 100, 108, 101, 18, 56, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, 111, + 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 118, 97, 108, 117, 101, 101, 110, + 116, 105, 116, 121, 46, 86, 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 83, 116, 114, + 101, 97, 109, 73, 110, 26, 57, 46, 101, 105, 103, 114, 46, 102, 117, 110, 99, 116, 105, + 111, 110, 115, 46, 112, 114, 111, 116, 111, 99, 111, 108, 46, 118, 97, 108, 117, 101, 101, + 110, 116, 105, 116, 121, 46, 86, 97, 108, 117, 101, 69, 110, 116, 105, 116, 121, 83, 116, + 114, 101, 97, 109, 79, 117, 116, 34, 3, 136, 2, 0, 40, 1, 48, 1>> + ) + end + + rpc :handle, + stream(Eigr.Functions.Protocol.Valueentity.ValueEntityStreamIn), + stream(Eigr.Functions.Protocol.Valueentity.ValueEntityStreamOut) +end + +defmodule Eigr.Functions.Protocol.Valueentity.ValueEntity.Stub do + @moduledoc false + use GRPC.Stub, service: Eigr.Functions.Protocol.Valueentity.ValueEntity.Service +end diff --git a/apps/eigr_protocol/lib/google/api/annotations.pb.ex b/apps/eigr_protocol/lib/google/api/annotations.pb.ex new file mode 100644 index 0000000..e69de29 diff --git a/apps/eigr_protocol/lib/google/api/auth.pb.ex b/apps/eigr_protocol/lib/google/api/auth.pb.ex new file mode 100644 index 0000000..f2a05b9 --- /dev/null +++ b/apps/eigr_protocol/lib/google/api/auth.pb.ex @@ -0,0 +1,175 @@ +defmodule Google.Api.Authentication do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + rules: [Google.Api.AuthenticationRule.t()], + providers: [Google.Api.AuthProvider.t()] + } + defstruct [:rules, :providers] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 14, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 18, 52, 10, 5, + 114, 117, 108, 101, 115, 24, 3, 32, 3, 40, 11, 50, 30, 46, 103, 111, 111, 103, 108, 101, + 46, 97, 112, 105, 46, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, + 82, 117, 108, 101, 82, 5, 114, 117, 108, 101, 115, 18, 54, 10, 9, 112, 114, 111, 118, 105, + 100, 101, 114, 115, 24, 4, 32, 3, 40, 11, 50, 24, 46, 103, 111, 111, 103, 108, 101, 46, + 97, 112, 105, 46, 65, 117, 116, 104, 80, 114, 111, 118, 105, 100, 101, 114, 82, 9, 112, + 114, 111, 118, 105, 100, 101, 114, 115>> + ) + end + + field :rules, 3, repeated: true, type: Google.Api.AuthenticationRule + field :providers, 4, repeated: true, type: Google.Api.AuthProvider +end + +defmodule Google.Api.AuthenticationRule do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + selector: String.t(), + oauth: Google.Api.OAuthRequirements.t() | nil, + allow_without_credential: boolean, + requirements: [Google.Api.AuthRequirement.t()] + } + defstruct [:selector, :oauth, :allow_without_credential, :requirements] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 18, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 82, 117, 108, + 101, 18, 26, 10, 8, 115, 101, 108, 101, 99, 116, 111, 114, 24, 1, 32, 1, 40, 9, 82, 8, + 115, 101, 108, 101, 99, 116, 111, 114, 18, 51, 10, 5, 111, 97, 117, 116, 104, 24, 2, 32, + 1, 40, 11, 50, 29, 46, 103, 111, 111, 103, 108, 101, 46, 97, 112, 105, 46, 79, 65, 117, + 116, 104, 82, 101, 113, 117, 105, 114, 101, 109, 101, 110, 116, 115, 82, 5, 111, 97, 117, + 116, 104, 18, 56, 10, 24, 97, 108, 108, 111, 119, 95, 119, 105, 116, 104, 111, 117, 116, + 95, 99, 114, 101, 100, 101, 110, 116, 105, 97, 108, 24, 5, 32, 1, 40, 8, 82, 22, 97, 108, + 108, 111, 119, 87, 105, 116, 104, 111, 117, 116, 67, 114, 101, 100, 101, 110, 116, 105, + 97, 108, 18, 63, 10, 12, 114, 101, 113, 117, 105, 114, 101, 109, 101, 110, 116, 115, 24, + 7, 32, 3, 40, 11, 50, 27, 46, 103, 111, 111, 103, 108, 101, 46, 97, 112, 105, 46, 65, 117, + 116, 104, 82, 101, 113, 117, 105, 114, 101, 109, 101, 110, 116, 82, 12, 114, 101, 113, + 117, 105, 114, 101, 109, 101, 110, 116, 115>> + ) + end + + field :selector, 1, type: :string + field :oauth, 2, type: Google.Api.OAuthRequirements + field :allow_without_credential, 5, type: :bool + field :requirements, 7, repeated: true, type: Google.Api.AuthRequirement +end + +defmodule Google.Api.JwtLocation do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + in: {atom, any}, + value_prefix: String.t() + } + defstruct [:in, :value_prefix] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 11, 74, 119, 116, 76, 111, 99, 97, 116, 105, 111, 110, 18, 24, 10, 6, 104, 101, 97, + 100, 101, 114, 24, 1, 32, 1, 40, 9, 72, 0, 82, 6, 104, 101, 97, 100, 101, 114, 18, 22, 10, + 5, 113, 117, 101, 114, 121, 24, 2, 32, 1, 40, 9, 72, 0, 82, 5, 113, 117, 101, 114, 121, + 18, 33, 10, 12, 118, 97, 108, 117, 101, 95, 112, 114, 101, 102, 105, 120, 24, 3, 32, 1, + 40, 9, 82, 11, 118, 97, 108, 117, 101, 80, 114, 101, 102, 105, 120, 66, 4, 10, 2, 105, + 110>> + ) + end + + oneof :in, 0 + field :header, 1, type: :string, oneof: 0 + field :query, 2, type: :string, oneof: 0 + field :value_prefix, 3, type: :string +end + +defmodule Google.Api.AuthProvider do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + id: String.t(), + issuer: String.t(), + jwks_uri: String.t(), + audiences: String.t(), + authorization_url: String.t(), + jwt_locations: [Google.Api.JwtLocation.t()] + } + defstruct [:id, :issuer, :jwks_uri, :audiences, :authorization_url, :jwt_locations] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 12, 65, 117, 116, 104, 80, 114, 111, 118, 105, 100, 101, 114, 18, 14, 10, 2, 105, 100, + 24, 1, 32, 1, 40, 9, 82, 2, 105, 100, 18, 22, 10, 6, 105, 115, 115, 117, 101, 114, 24, 2, + 32, 1, 40, 9, 82, 6, 105, 115, 115, 117, 101, 114, 18, 25, 10, 8, 106, 119, 107, 115, 95, + 117, 114, 105, 24, 3, 32, 1, 40, 9, 82, 7, 106, 119, 107, 115, 85, 114, 105, 18, 28, 10, + 9, 97, 117, 100, 105, 101, 110, 99, 101, 115, 24, 4, 32, 1, 40, 9, 82, 9, 97, 117, 100, + 105, 101, 110, 99, 101, 115, 18, 43, 10, 17, 97, 117, 116, 104, 111, 114, 105, 122, 97, + 116, 105, 111, 110, 95, 117, 114, 108, 24, 5, 32, 1, 40, 9, 82, 16, 97, 117, 116, 104, + 111, 114, 105, 122, 97, 116, 105, 111, 110, 85, 114, 108, 18, 60, 10, 13, 106, 119, 116, + 95, 108, 111, 99, 97, 116, 105, 111, 110, 115, 24, 6, 32, 3, 40, 11, 50, 23, 46, 103, 111, + 111, 103, 108, 101, 46, 97, 112, 105, 46, 74, 119, 116, 76, 111, 99, 97, 116, 105, 111, + 110, 82, 12, 106, 119, 116, 76, 111, 99, 97, 116, 105, 111, 110, 115>> + ) + end + + field :id, 1, type: :string + field :issuer, 2, type: :string + field :jwks_uri, 3, type: :string + field :audiences, 4, type: :string + field :authorization_url, 5, type: :string + field :jwt_locations, 6, repeated: true, type: Google.Api.JwtLocation +end + +defmodule Google.Api.OAuthRequirements do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + canonical_scopes: String.t() + } + defstruct [:canonical_scopes] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 17, 79, 65, 117, 116, 104, 82, 101, 113, 117, 105, 114, 101, 109, 101, 110, 116, 115, + 18, 41, 10, 16, 99, 97, 110, 111, 110, 105, 99, 97, 108, 95, 115, 99, 111, 112, 101, 115, + 24, 1, 32, 1, 40, 9, 82, 15, 99, 97, 110, 111, 110, 105, 99, 97, 108, 83, 99, 111, 112, + 101, 115>> + ) + end + + field :canonical_scopes, 1, type: :string +end + +defmodule Google.Api.AuthRequirement do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + provider_id: String.t(), + audiences: String.t() + } + defstruct [:provider_id, :audiences] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 15, 65, 117, 116, 104, 82, 101, 113, 117, 105, 114, 101, 109, 101, 110, 116, 18, 31, + 10, 11, 112, 114, 111, 118, 105, 100, 101, 114, 95, 105, 100, 24, 1, 32, 1, 40, 9, 82, 10, + 112, 114, 111, 118, 105, 100, 101, 114, 73, 100, 18, 28, 10, 9, 97, 117, 100, 105, 101, + 110, 99, 101, 115, 24, 2, 32, 1, 40, 9, 82, 9, 97, 117, 100, 105, 101, 110, 99, 101, 115>> + ) + end + + field :provider_id, 1, type: :string + field :audiences, 2, type: :string +end diff --git a/apps/eigr_protocol/lib/google/api/http.pb.ex b/apps/eigr_protocol/lib/google/api/http.pb.ex new file mode 100644 index 0000000..ba11776 --- /dev/null +++ b/apps/eigr_protocol/lib/google/api/http.pb.ex @@ -0,0 +1,98 @@ +defmodule Google.Api.Http do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + rules: [Google.Api.HttpRule.t()], + fully_decode_reserved_expansion: boolean + } + defstruct [:rules, :fully_decode_reserved_expansion] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 4, 72, 116, 116, 112, 18, 42, 10, 5, 114, 117, 108, 101, 115, 24, 1, 32, 3, 40, 11, + 50, 20, 46, 103, 111, 111, 103, 108, 101, 46, 97, 112, 105, 46, 72, 116, 116, 112, 82, + 117, 108, 101, 82, 5, 114, 117, 108, 101, 115, 18, 69, 10, 31, 102, 117, 108, 108, 121, + 95, 100, 101, 99, 111, 100, 101, 95, 114, 101, 115, 101, 114, 118, 101, 100, 95, 101, 120, + 112, 97, 110, 115, 105, 111, 110, 24, 2, 32, 1, 40, 8, 82, 28, 102, 117, 108, 108, 121, + 68, 101, 99, 111, 100, 101, 82, 101, 115, 101, 114, 118, 101, 100, 69, 120, 112, 97, 110, + 115, 105, 111, 110>> + ) + end + + field :rules, 1, repeated: true, type: Google.Api.HttpRule + field :fully_decode_reserved_expansion, 2, type: :bool +end + +defmodule Google.Api.HttpRule do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + pattern: {atom, any}, + selector: String.t(), + body: String.t(), + response_body: String.t(), + additional_bindings: [Google.Api.HttpRule.t()] + } + defstruct [:pattern, :selector, :body, :response_body, :additional_bindings] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 8, 72, 116, 116, 112, 82, 117, 108, 101, 18, 26, 10, 8, 115, 101, 108, 101, 99, 116, + 111, 114, 24, 1, 32, 1, 40, 9, 82, 8, 115, 101, 108, 101, 99, 116, 111, 114, 18, 18, 10, + 3, 103, 101, 116, 24, 2, 32, 1, 40, 9, 72, 0, 82, 3, 103, 101, 116, 18, 18, 10, 3, 112, + 117, 116, 24, 3, 32, 1, 40, 9, 72, 0, 82, 3, 112, 117, 116, 18, 20, 10, 4, 112, 111, 115, + 116, 24, 4, 32, 1, 40, 9, 72, 0, 82, 4, 112, 111, 115, 116, 18, 24, 10, 6, 100, 101, 108, + 101, 116, 101, 24, 5, 32, 1, 40, 9, 72, 0, 82, 6, 100, 101, 108, 101, 116, 101, 18, 22, + 10, 5, 112, 97, 116, 99, 104, 24, 6, 32, 1, 40, 9, 72, 0, 82, 5, 112, 97, 116, 99, 104, + 18, 55, 10, 6, 99, 117, 115, 116, 111, 109, 24, 8, 32, 1, 40, 11, 50, 29, 46, 103, 111, + 111, 103, 108, 101, 46, 97, 112, 105, 46, 67, 117, 115, 116, 111, 109, 72, 116, 116, 112, + 80, 97, 116, 116, 101, 114, 110, 72, 0, 82, 6, 99, 117, 115, 116, 111, 109, 18, 18, 10, 4, + 98, 111, 100, 121, 24, 7, 32, 1, 40, 9, 82, 4, 98, 111, 100, 121, 18, 35, 10, 13, 114, + 101, 115, 112, 111, 110, 115, 101, 95, 98, 111, 100, 121, 24, 12, 32, 1, 40, 9, 82, 12, + 114, 101, 115, 112, 111, 110, 115, 101, 66, 111, 100, 121, 18, 69, 10, 19, 97, 100, 100, + 105, 116, 105, 111, 110, 97, 108, 95, 98, 105, 110, 100, 105, 110, 103, 115, 24, 11, 32, + 3, 40, 11, 50, 20, 46, 103, 111, 111, 103, 108, 101, 46, 97, 112, 105, 46, 72, 116, 116, + 112, 82, 117, 108, 101, 82, 18, 97, 100, 100, 105, 116, 105, 111, 110, 97, 108, 66, 105, + 110, 100, 105, 110, 103, 115, 66, 9, 10, 7, 112, 97, 116, 116, 101, 114, 110>> + ) + end + + oneof :pattern, 0 + field :selector, 1, type: :string + field :get, 2, type: :string, oneof: 0 + field :put, 3, type: :string, oneof: 0 + field :post, 4, type: :string, oneof: 0 + field :delete, 5, type: :string, oneof: 0 + field :patch, 6, type: :string, oneof: 0 + field :custom, 8, type: Google.Api.CustomHttpPattern, oneof: 0 + field :body, 7, type: :string + field :response_body, 12, type: :string + field :additional_bindings, 11, repeated: true, type: Google.Api.HttpRule +end + +defmodule Google.Api.CustomHttpPattern do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + kind: String.t(), + path: String.t() + } + defstruct [:kind, :path] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 17, 67, 117, 115, 116, 111, 109, 72, 116, 116, 112, 80, 97, 116, 116, 101, 114, 110, + 18, 18, 10, 4, 107, 105, 110, 100, 24, 1, 32, 1, 40, 9, 82, 4, 107, 105, 110, 100, 18, 18, + 10, 4, 112, 97, 116, 104, 24, 2, 32, 1, 40, 9, 82, 4, 112, 97, 116, 104>> + ) + end + + field :kind, 1, type: :string + field :path, 2, type: :string +end diff --git a/apps/eigr_protocol/lib/google/api/httpbody.pb.ex b/apps/eigr_protocol/lib/google/api/httpbody.pb.ex new file mode 100644 index 0000000..fe675e8 --- /dev/null +++ b/apps/eigr_protocol/lib/google/api/httpbody.pb.ex @@ -0,0 +1,27 @@ +defmodule Google.Api.HttpBody do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + content_type: String.t(), + data: binary, + extensions: [Google.Protobuf.Any.t()] + } + defstruct [:content_type, :data, :extensions] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 8, 72, 116, 116, 112, 66, 111, 100, 121, 18, 33, 10, 12, 99, 111, 110, 116, 101, 110, + 116, 95, 116, 121, 112, 101, 24, 1, 32, 1, 40, 9, 82, 11, 99, 111, 110, 116, 101, 110, + 116, 84, 121, 112, 101, 18, 18, 10, 4, 100, 97, 116, 97, 24, 2, 32, 1, 40, 12, 82, 4, 100, + 97, 116, 97, 18, 52, 10, 10, 101, 120, 116, 101, 110, 115, 105, 111, 110, 115, 24, 3, 32, + 3, 40, 11, 50, 20, 46, 103, 111, 111, 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, + 102, 46, 65, 110, 121, 82, 10, 101, 120, 116, 101, 110, 115, 105, 111, 110, 115>> + ) + end + + field :content_type, 1, type: :string + field :data, 2, type: :bytes + field :extensions, 3, repeated: true, type: Google.Protobuf.Any +end diff --git a/apps/eigr_protocol/lib/google/api/source_info.pb.ex b/apps/eigr_protocol/lib/google/api/source_info.pb.ex new file mode 100644 index 0000000..c2121b0 --- /dev/null +++ b/apps/eigr_protocol/lib/google/api/source_info.pb.ex @@ -0,0 +1,21 @@ +defmodule Google.Api.SourceInfo do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + source_files: [Google.Protobuf.Any.t()] + } + defstruct [:source_files] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 10, 83, 111, 117, 114, 99, 101, 73, 110, 102, 111, 18, 55, 10, 12, 115, 111, 117, 114, + 99, 101, 95, 102, 105, 108, 101, 115, 24, 1, 32, 3, 40, 11, 50, 20, 46, 103, 111, 111, + 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 65, 110, 121, 82, 11, 115, + 111, 117, 114, 99, 101, 70, 105, 108, 101, 115>> + ) + end + + field :source_files, 1, repeated: true, type: Google.Protobuf.Any +end diff --git a/apps/eigr_protocol/lib/grpc/reflection/v1alpha/reflection.pb.ex b/apps/eigr_protocol/lib/grpc/reflection/v1alpha/reflection.pb.ex new file mode 100644 index 0000000..9fb40bc --- /dev/null +++ b/apps/eigr_protocol/lib/grpc/reflection/v1alpha/reflection.pb.ex @@ -0,0 +1,278 @@ +defmodule Grpc.Reflection.V1alpha.ServerReflectionRequest do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + message_request: {atom, any}, + host: String.t() + } + defstruct [:message_request, :host] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 23, 83, 101, 114, 118, 101, 114, 82, 101, 102, 108, 101, 99, 116, 105, 111, 110, 82, + 101, 113, 117, 101, 115, 116, 18, 18, 10, 4, 104, 111, 115, 116, 24, 1, 32, 1, 40, 9, 82, + 4, 104, 111, 115, 116, 18, 42, 10, 16, 102, 105, 108, 101, 95, 98, 121, 95, 102, 105, 108, + 101, 110, 97, 109, 101, 24, 3, 32, 1, 40, 9, 72, 0, 82, 14, 102, 105, 108, 101, 66, 121, + 70, 105, 108, 101, 110, 97, 109, 101, 18, 54, 10, 22, 102, 105, 108, 101, 95, 99, 111, + 110, 116, 97, 105, 110, 105, 110, 103, 95, 115, 121, 109, 98, 111, 108, 24, 4, 32, 1, 40, + 9, 72, 0, 82, 20, 102, 105, 108, 101, 67, 111, 110, 116, 97, 105, 110, 105, 110, 103, 83, + 121, 109, 98, 111, 108, 18, 103, 10, 25, 102, 105, 108, 101, 95, 99, 111, 110, 116, 97, + 105, 110, 105, 110, 103, 95, 101, 120, 116, 101, 110, 115, 105, 111, 110, 24, 5, 32, 1, + 40, 11, 50, 41, 46, 103, 114, 112, 99, 46, 114, 101, 102, 108, 101, 99, 116, 105, 111, + 110, 46, 118, 49, 97, 108, 112, 104, 97, 46, 69, 120, 116, 101, 110, 115, 105, 111, 110, + 82, 101, 113, 117, 101, 115, 116, 72, 0, 82, 23, 102, 105, 108, 101, 67, 111, 110, 116, + 97, 105, 110, 105, 110, 103, 69, 120, 116, 101, 110, 115, 105, 111, 110, 18, 66, 10, 29, + 97, 108, 108, 95, 101, 120, 116, 101, 110, 115, 105, 111, 110, 95, 110, 117, 109, 98, 101, + 114, 115, 95, 111, 102, 95, 116, 121, 112, 101, 24, 6, 32, 1, 40, 9, 72, 0, 82, 25, 97, + 108, 108, 69, 120, 116, 101, 110, 115, 105, 111, 110, 78, 117, 109, 98, 101, 114, 115, 79, + 102, 84, 121, 112, 101, 18, 37, 10, 13, 108, 105, 115, 116, 95, 115, 101, 114, 118, 105, + 99, 101, 115, 24, 7, 32, 1, 40, 9, 72, 0, 82, 12, 108, 105, 115, 116, 83, 101, 114, 118, + 105, 99, 101, 115, 66, 17, 10, 15, 109, 101, 115, 115, 97, 103, 101, 95, 114, 101, 113, + 117, 101, 115, 116>> + ) + end + + oneof :message_request, 0 + field :host, 1, type: :string + field :file_by_filename, 3, type: :string, oneof: 0 + field :file_containing_symbol, 4, type: :string, oneof: 0 + field :file_containing_extension, 5, type: Grpc.Reflection.V1alpha.ExtensionRequest, oneof: 0 + field :all_extension_numbers_of_type, 6, type: :string, oneof: 0 + field :list_services, 7, type: :string, oneof: 0 +end + +defmodule Grpc.Reflection.V1alpha.ExtensionRequest do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + containing_type: String.t(), + extension_number: integer + } + defstruct [:containing_type, :extension_number] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 16, 69, 120, 116, 101, 110, 115, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 18, + 39, 10, 15, 99, 111, 110, 116, 97, 105, 110, 105, 110, 103, 95, 116, 121, 112, 101, 24, 1, + 32, 1, 40, 9, 82, 14, 99, 111, 110, 116, 97, 105, 110, 105, 110, 103, 84, 121, 112, 101, + 18, 41, 10, 16, 101, 120, 116, 101, 110, 115, 105, 111, 110, 95, 110, 117, 109, 98, 101, + 114, 24, 2, 32, 1, 40, 5, 82, 15, 101, 120, 116, 101, 110, 115, 105, 111, 110, 78, 117, + 109, 98, 101, 114>> + ) + end + + field :containing_type, 1, type: :string + field :extension_number, 2, type: :int32 +end + +defmodule Grpc.Reflection.V1alpha.ServerReflectionResponse do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + message_response: {atom, any}, + valid_host: String.t(), + original_request: Grpc.Reflection.V1alpha.ServerReflectionRequest.t() | nil + } + defstruct [:message_response, :valid_host, :original_request] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 24, 83, 101, 114, 118, 101, 114, 82, 101, 102, 108, 101, 99, 116, 105, 111, 110, 82, + 101, 115, 112, 111, 110, 115, 101, 18, 29, 10, 10, 118, 97, 108, 105, 100, 95, 104, 111, + 115, 116, 24, 1, 32, 1, 40, 9, 82, 9, 118, 97, 108, 105, 100, 72, 111, 115, 116, 18, 91, + 10, 16, 111, 114, 105, 103, 105, 110, 97, 108, 95, 114, 101, 113, 117, 101, 115, 116, 24, + 2, 32, 1, 40, 11, 50, 48, 46, 103, 114, 112, 99, 46, 114, 101, 102, 108, 101, 99, 116, + 105, 111, 110, 46, 118, 49, 97, 108, 112, 104, 97, 46, 83, 101, 114, 118, 101, 114, 82, + 101, 102, 108, 101, 99, 116, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 82, 15, 111, + 114, 105, 103, 105, 110, 97, 108, 82, 101, 113, 117, 101, 115, 116, 18, 107, 10, 24, 102, + 105, 108, 101, 95, 100, 101, 115, 99, 114, 105, 112, 116, 111, 114, 95, 114, 101, 115, + 112, 111, 110, 115, 101, 24, 4, 32, 1, 40, 11, 50, 47, 46, 103, 114, 112, 99, 46, 114, + 101, 102, 108, 101, 99, 116, 105, 111, 110, 46, 118, 49, 97, 108, 112, 104, 97, 46, 70, + 105, 108, 101, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 82, 101, 115, 112, 111, + 110, 115, 101, 72, 0, 82, 22, 102, 105, 108, 101, 68, 101, 115, 99, 114, 105, 112, 116, + 111, 114, 82, 101, 115, 112, 111, 110, 115, 101, 18, 119, 10, 30, 97, 108, 108, 95, 101, + 120, 116, 101, 110, 115, 105, 111, 110, 95, 110, 117, 109, 98, 101, 114, 115, 95, 114, + 101, 115, 112, 111, 110, 115, 101, 24, 5, 32, 1, 40, 11, 50, 48, 46, 103, 114, 112, 99, + 46, 114, 101, 102, 108, 101, 99, 116, 105, 111, 110, 46, 118, 49, 97, 108, 112, 104, 97, + 46, 69, 120, 116, 101, 110, 115, 105, 111, 110, 78, 117, 109, 98, 101, 114, 82, 101, 115, + 112, 111, 110, 115, 101, 72, 0, 82, 27, 97, 108, 108, 69, 120, 116, 101, 110, 115, 105, + 111, 110, 78, 117, 109, 98, 101, 114, 115, 82, 101, 115, 112, 111, 110, 115, 101, 18, 100, + 10, 22, 108, 105, 115, 116, 95, 115, 101, 114, 118, 105, 99, 101, 115, 95, 114, 101, 115, + 112, 111, 110, 115, 101, 24, 6, 32, 1, 40, 11, 50, 44, 46, 103, 114, 112, 99, 46, 114, + 101, 102, 108, 101, 99, 116, 105, 111, 110, 46, 118, 49, 97, 108, 112, 104, 97, 46, 76, + 105, 115, 116, 83, 101, 114, 118, 105, 99, 101, 82, 101, 115, 112, 111, 110, 115, 101, 72, + 0, 82, 20, 108, 105, 115, 116, 83, 101, 114, 118, 105, 99, 101, 115, 82, 101, 115, 112, + 111, 110, 115, 101, 18, 79, 10, 14, 101, 114, 114, 111, 114, 95, 114, 101, 115, 112, 111, + 110, 115, 101, 24, 7, 32, 1, 40, 11, 50, 38, 46, 103, 114, 112, 99, 46, 114, 101, 102, + 108, 101, 99, 116, 105, 111, 110, 46, 118, 49, 97, 108, 112, 104, 97, 46, 69, 114, 114, + 111, 114, 82, 101, 115, 112, 111, 110, 115, 101, 72, 0, 82, 13, 101, 114, 114, 111, 114, + 82, 101, 115, 112, 111, 110, 115, 101, 66, 18, 10, 16, 109, 101, 115, 115, 97, 103, 101, + 95, 114, 101, 115, 112, 111, 110, 115, 101>> + ) + end + + oneof :message_response, 0 + field :valid_host, 1, type: :string + field :original_request, 2, type: Grpc.Reflection.V1alpha.ServerReflectionRequest + + field :file_descriptor_response, 4, + type: Grpc.Reflection.V1alpha.FileDescriptorResponse, + oneof: 0 + + field :all_extension_numbers_response, 5, + type: Grpc.Reflection.V1alpha.ExtensionNumberResponse, + oneof: 0 + + field :list_services_response, 6, type: Grpc.Reflection.V1alpha.ListServiceResponse, oneof: 0 + field :error_response, 7, type: Grpc.Reflection.V1alpha.ErrorResponse, oneof: 0 +end + +defmodule Grpc.Reflection.V1alpha.FileDescriptorResponse do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + file_descriptor_proto: [binary] + } + defstruct [:file_descriptor_proto] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 22, 70, 105, 108, 101, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 82, 101, 115, + 112, 111, 110, 115, 101, 18, 50, 10, 21, 102, 105, 108, 101, 95, 100, 101, 115, 99, 114, + 105, 112, 116, 111, 114, 95, 112, 114, 111, 116, 111, 24, 1, 32, 3, 40, 12, 82, 19, 102, + 105, 108, 101, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 80, 114, 111, 116, 111>> + ) + end + + field :file_descriptor_proto, 1, repeated: true, type: :bytes +end + +defmodule Grpc.Reflection.V1alpha.ExtensionNumberResponse do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + base_type_name: String.t(), + extension_number: [integer] + } + defstruct [:base_type_name, :extension_number] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 23, 69, 120, 116, 101, 110, 115, 105, 111, 110, 78, 117, 109, 98, 101, 114, 82, 101, + 115, 112, 111, 110, 115, 101, 18, 36, 10, 14, 98, 97, 115, 101, 95, 116, 121, 112, 101, + 95, 110, 97, 109, 101, 24, 1, 32, 1, 40, 9, 82, 12, 98, 97, 115, 101, 84, 121, 112, 101, + 78, 97, 109, 101, 18, 41, 10, 16, 101, 120, 116, 101, 110, 115, 105, 111, 110, 95, 110, + 117, 109, 98, 101, 114, 24, 2, 32, 3, 40, 5, 82, 15, 101, 120, 116, 101, 110, 115, 105, + 111, 110, 78, 117, 109, 98, 101, 114>> + ) + end + + field :base_type_name, 1, type: :string + field :extension_number, 2, repeated: true, type: :int32 +end + +defmodule Grpc.Reflection.V1alpha.ListServiceResponse do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + service: [Grpc.Reflection.V1alpha.ServiceResponse.t()] + } + defstruct [:service] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 19, 76, 105, 115, 116, 83, 101, 114, 118, 105, 99, 101, 82, 101, 115, 112, 111, 110, + 115, 101, 18, 66, 10, 7, 115, 101, 114, 118, 105, 99, 101, 24, 1, 32, 3, 40, 11, 50, 40, + 46, 103, 114, 112, 99, 46, 114, 101, 102, 108, 101, 99, 116, 105, 111, 110, 46, 118, 49, + 97, 108, 112, 104, 97, 46, 83, 101, 114, 118, 105, 99, 101, 82, 101, 115, 112, 111, 110, + 115, 101, 82, 7, 115, 101, 114, 118, 105, 99, 101>> + ) + end + + field :service, 1, repeated: true, type: Grpc.Reflection.V1alpha.ServiceResponse +end + +defmodule Grpc.Reflection.V1alpha.ServiceResponse do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + name: String.t() + } + defstruct [:name] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 15, 83, 101, 114, 118, 105, 99, 101, 82, 101, 115, 112, 111, 110, 115, 101, 18, 18, + 10, 4, 110, 97, 109, 101, 24, 1, 32, 1, 40, 9, 82, 4, 110, 97, 109, 101>> + ) + end + + field :name, 1, type: :string +end + +defmodule Grpc.Reflection.V1alpha.ErrorResponse do + @moduledoc false + use Protobuf, syntax: :proto3 + + @type t :: %__MODULE__{ + error_code: integer, + error_message: String.t() + } + defstruct [:error_code, :error_message] + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.DescriptorProto.decode( + <<10, 13, 69, 114, 114, 111, 114, 82, 101, 115, 112, 111, 110, 115, 101, 18, 29, 10, 10, + 101, 114, 114, 111, 114, 95, 99, 111, 100, 101, 24, 1, 32, 1, 40, 5, 82, 9, 101, 114, 114, + 111, 114, 67, 111, 100, 101, 18, 35, 10, 13, 101, 114, 114, 111, 114, 95, 109, 101, 115, + 115, 97, 103, 101, 24, 2, 32, 1, 40, 9, 82, 12, 101, 114, 114, 111, 114, 77, 101, 115, + 115, 97, 103, 101>> + ) + end + + field :error_code, 1, type: :int32 + field :error_message, 2, type: :string +end + +defmodule Grpc.Reflection.V1alpha.ServerReflection.Service do + @moduledoc false + use GRPC.Service, name: "grpc.reflection.v1alpha.ServerReflection" + + def descriptor do + # credo:disable-for-next-line + Elixir.Google.Protobuf.ServiceDescriptorProto.decode( + <<10, 16, 83, 101, 114, 118, 101, 114, 82, 101, 102, 108, 101, 99, 116, 105, 111, 110, 18, + 127, 10, 20, 83, 101, 114, 118, 101, 114, 82, 101, 102, 108, 101, 99, 116, 105, 111, 110, + 73, 110, 102, 111, 18, 48, 46, 103, 114, 112, 99, 46, 114, 101, 102, 108, 101, 99, 116, + 105, 111, 110, 46, 118, 49, 97, 108, 112, 104, 97, 46, 83, 101, 114, 118, 101, 114, 82, + 101, 102, 108, 101, 99, 116, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 26, 49, 46, + 103, 114, 112, 99, 46, 114, 101, 102, 108, 101, 99, 116, 105, 111, 110, 46, 118, 49, 97, + 108, 112, 104, 97, 46, 83, 101, 114, 118, 101, 114, 82, 101, 102, 108, 101, 99, 116, 105, + 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 40, 1, 48, 1>> + ) + end + + rpc :ServerReflectionInfo, + stream(Grpc.Reflection.V1alpha.ServerReflectionRequest), + stream(Grpc.Reflection.V1alpha.ServerReflectionResponse) +end + +defmodule Grpc.Reflection.V1alpha.ServerReflection.Stub do + @moduledoc false + use GRPC.Stub, service: Grpc.Reflection.V1alpha.ServerReflection.Service +end diff --git a/apps/eigr_protocol/mix.exs b/apps/eigr_protocol/mix.exs index 563ce6f..a2671b0 100644 --- a/apps/eigr_protocol/mix.exs +++ b/apps/eigr_protocol/mix.exs @@ -25,9 +25,10 @@ defmodule EigrProtocol.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ - # {:dep_from_hexpm, "~> 0.3.0"}, - # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}, - # {:sibling_app_in_umbrella, in_umbrella: true} + {:google_protos, "~> 0.2.0"}, + {:protobuf, "~> 0.9.0", override: true}, + {:grpc, github: "elixir-grpc/grpc", override: true}, + {:cowlib, "~> 2.11", override: true} ] end end diff --git a/apps/eigr_protocol/priv/protos/eigr/functions/example/shoppingcart/persistence/domain.proto b/apps/eigr_protocol/priv/protos/eigr/functions/example/shoppingcart/persistence/domain.proto new file mode 100644 index 0000000..c827b80 --- /dev/null +++ b/apps/eigr_protocol/priv/protos/eigr/functions/example/shoppingcart/persistence/domain.proto @@ -0,0 +1,27 @@ +// These are the messages that get persisted - the events, plus the current state (Cart) for snapshots. +syntax = "proto3"; + +package com.example.shoppingcart.persistence; + +option go_package = "persistence"; + +message LineItem { + string productId = 1; + string name = 2; + int32 quantity = 3; +} + +// The item added event. +message ItemAdded { + LineItem item = 1; +} + +// The item removed event. +message ItemRemoved { + string productId = 1; +} + +// The shopping cart state. +message Cart { + repeated LineItem items = 1; +} diff --git a/apps/eigr_protocol/priv/protos/eigr/functions/example/shoppingcart/shoppingcart.proto b/apps/eigr_protocol/priv/protos/eigr/functions/example/shoppingcart/shoppingcart.proto new file mode 100644 index 0000000..27e1baf --- /dev/null +++ b/apps/eigr_protocol/priv/protos/eigr/functions/example/shoppingcart/shoppingcart.proto @@ -0,0 +1,63 @@ +// This is the public API offered by the shopping cart entity. +syntax = "proto3"; + +import "google/protobuf/empty.proto"; +import "cloudstate/entity_key.proto"; +import "cloudstate/eventing.proto"; +import "google/api/annotations.proto"; +import "google/api/http.proto"; +import "google/api/httpbody.proto"; + +package com.example.shoppingcart; + +option go_package = "tck/shoppingcart"; + +message AddLineItem { + string user_id = 1 [(.cloudstate.entity_key) = true]; + string product_id = 2; + string name = 3; + int32 quantity = 4; +} + +message RemoveLineItem { + string user_id = 1 [(.cloudstate.entity_key) = true]; + string product_id = 2; +} + +message GetShoppingCart { + string user_id = 1 [(.cloudstate.entity_key) = true]; +} + +message LineItem { + string product_id = 1; + string name = 2; + int32 quantity = 3; +} + +message Cart { + repeated LineItem items = 1; +} + +service ShoppingCart { + rpc AddItem(AddLineItem) returns (google.protobuf.Empty) { + option (google.api.http) = { + post: "/cart/{user_id}/items/add", + body: "*", + }; + option (.cloudstate.eventing).in = "items"; + } + + rpc RemoveItem(RemoveLineItem) returns (google.protobuf.Empty) { + option (google.api.http).post = "/cart/{user_id}/items/{product_id}/remove"; + } + + rpc GetCart(GetShoppingCart) returns (Cart) { + option (google.api.http) = { + get: "/carts/{user_id}", + additional_bindings: { + get: "/carts/{user_id}/items", + response_body: "items" + } + }; + } +} diff --git a/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/annotations.proto b/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/annotations.proto new file mode 100644 index 0000000..f7bcab1 --- /dev/null +++ b/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/annotations.proto @@ -0,0 +1,32 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/http.proto"; +import "google/protobuf/descriptor.proto"; + +option csharp_namespace = "Google.Protobuf"; +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "AnnotationsProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.MethodOptions { + // See `HttpRule`. + HttpRule http = 72295728; +} diff --git a/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/auth.proto b/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/auth.proto new file mode 100644 index 0000000..1a1cf26 --- /dev/null +++ b/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/auth.proto @@ -0,0 +1,228 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "AuthProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// `Authentication` defines the authentication configuration for an API. +// +// Example for an API targeted for external use: +// +// name: calendar.googleapis.com +// authentication: +// providers: +// - id: google_calendar_auth +// jwks_uri: https://www.googleapis.com/oauth2/v1/certs +// issuer: https://securetoken.google.com +// rules: +// - selector: "*" +// requirements: +// provider_id: google_calendar_auth +message Authentication { + // A list of authentication rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated AuthenticationRule rules = 3; + + // Defines a set of authentication providers that a service supports. + repeated AuthProvider providers = 4; +} + +// Authentication rules for the service. +// +// By default, if a method has any authentication requirements, every request +// must include a valid credential matching one of the requirements. +// It's an error to include more than one kind of credential in a single +// request. +// +// If a method doesn't have any auth requirements, request credentials will be +// ignored. +message AuthenticationRule { + // Selects the methods to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax details. + string selector = 1; + + // The requirements for OAuth credentials. + OAuthRequirements oauth = 2; + + // If true, the service accepts API keys without any other credential. + // This flag only applies to HTTP and gRPC requests. + bool allow_without_credential = 5; + + // Requirements for additional authentication providers. + repeated AuthRequirement requirements = 7; +} + +// Specifies a location to extract JWT from an API request. +message JwtLocation { + oneof in { + // Specifies HTTP header name to extract JWT token. + string header = 1; + + // Specifies URL query parameter name to extract JWT token. + string query = 2; + } + + // The value prefix. The value format is "value_prefix{token}" + // Only applies to "in" header type. Must be empty for "in" query type. + // If not empty, the header value has to match (case sensitive) this prefix. + // If not matched, JWT will not be extracted. If matched, JWT will be + // extracted after the prefix is removed. + // + // For example, for "Authorization: Bearer {JWT}", + // value_prefix="Bearer " with a space at the end. + string value_prefix = 3; +} + +// Configuration for an authentication provider, including support for +// [JSON Web Token +// (JWT)](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32). +message AuthProvider { + // The unique identifier of the auth provider. It will be referred to by + // `AuthRequirement.provider_id`. + // + // Example: "bookstore_auth". + string id = 1; + + // Identifies the principal that issued the JWT. See + // https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-4.1.1 + // Usually a URL or an email address. + // + // Example: https://securetoken.google.com + // Example: 1234567-compute@developer.gserviceaccount.com + string issuer = 2; + + // URL of the provider's public key set to validate signature of the JWT. See + // [OpenID + // Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata). + // Optional if the key set document: + // - can be retrieved from + // [OpenID + // Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) + // of the issuer. + // - can be inferred from the email domain of the issuer (e.g. a Google + // service account). + // + // Example: https://www.googleapis.com/oauth2/v1/certs + string jwks_uri = 3; + + // The list of JWT + // [audiences](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-4.1.3). + // that are allowed to access. A JWT containing any of these audiences will + // be accepted. When this setting is absent, JWTs with audiences: + // - "https://[service.name]/[google.protobuf.Api.name]" + // - "https://[service.name]/" + // will be accepted. + // For example, if no audiences are in the setting, LibraryService API will + // accept JWTs with the following audiences: + // - + // https://library-example.googleapis.com/google.example.library.v1.LibraryService + // - https://library-example.googleapis.com/ + // + // Example: + // + // audiences: bookstore_android.apps.googleusercontent.com, + // bookstore_web.apps.googleusercontent.com + string audiences = 4; + + // Redirect URL if JWT token is required but not present or is expired. + // Implement authorizationUrl of securityDefinitions in OpenAPI spec. + string authorization_url = 5; + + // Defines the locations to extract the JWT. + // + // JWT locations can be either from HTTP headers or URL query parameters. + // The rule is that the first match wins. The checking order is: checking + // all headers first, then URL query parameters. + // + // If not specified, default to use following 3 locations: + // 1) Authorization: Bearer + // 2) x-goog-iap-jwt-assertion + // 3) access_token query parameter + // + // Default locations can be specified as followings: + // jwt_locations: + // - header: Authorization + // value_prefix: "Bearer " + // - header: x-goog-iap-jwt-assertion + // - query: access_token + repeated JwtLocation jwt_locations = 6; +} + +// OAuth scopes are a way to define data and permissions on data. For example, +// there are scopes defined for "Read-only access to Google Calendar" and +// "Access to Cloud Platform". Users can consent to a scope for an application, +// giving it permission to access that data on their behalf. +// +// OAuth scope specifications should be fairly coarse grained; a user will need +// to see and understand the text description of what your scope means. +// +// In most cases: use one or at most two OAuth scopes for an entire family of +// products. If your product has multiple APIs, you should probably be sharing +// the OAuth scope across all of those APIs. +// +// When you need finer grained OAuth consent screens: talk with your product +// management about how developers will use them in practice. +// +// Please note that even though each of the canonical scopes is enough for a +// request to be accepted and passed to the backend, a request can still fail +// due to the backend requiring additional scopes or permissions. +message OAuthRequirements { + // The list of publicly documented OAuth scopes that are allowed access. An + // OAuth token containing any of these scopes will be accepted. + // + // Example: + // + // canonical_scopes: https://www.googleapis.com/auth/calendar, + // https://www.googleapis.com/auth/calendar.read + string canonical_scopes = 1; +} + +// User-defined authentication requirements, including support for +// [JSON Web Token +// (JWT)](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32). +message AuthRequirement { + // [id][google.api.AuthProvider.id] from authentication provider. + // + // Example: + // + // provider_id: bookstore_auth + string provider_id = 1; + + // NOTE: This will be deprecated soon, once AuthProvider.audiences is + // implemented and accepted in all the runtime components. + // + // The list of JWT + // [audiences](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-4.1.3). + // that are allowed to access. A JWT containing any of these audiences will + // be accepted. When this setting is absent, only JWTs with audience + // "https://[Service_name][google.api.Service.name]/[API_name][google.protobuf.Api.name]" + // will be accepted. For example, if no audiences are in the setting, + // LibraryService API will only accept JWTs with the following audience + // "https://library-example.googleapis.com/google.example.library.v1.LibraryService". + // + // Example: + // + // audiences: bookstore_android.apps.googleusercontent.com, + // bookstore_web.apps.googleusercontent.com + string audiences = 2; +} \ No newline at end of file diff --git a/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/http.proto b/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/http.proto new file mode 100644 index 0000000..d554871 --- /dev/null +++ b/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/http.proto @@ -0,0 +1,377 @@ +// Copyright 2019 Google LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +package google.api; + +option csharp_namespace = "Google.Protobuf"; +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "HttpProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Defines the HTTP configuration for an API service. It contains a list of +// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method +// to one or more HTTP REST API methods. +message Http { + // A list of HTTP configuration rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated HttpRule rules = 1; + + // When set to true, URL path parameters will be fully URI-decoded except in + // cases of single segment matches in reserved expansion, where "%2F" will be + // left encoded. + // + // The default behavior is to not decode RFC 6570 reserved characters in multi + // segment matches. + bool fully_decode_reserved_expansion = 2; +} + +// # gRPC Transcoding +// +// gRPC Transcoding is a feature for mapping between a gRPC method and one or +// more HTTP REST endpoints. It allows developers to build a single API service +// that supports both gRPC APIs and REST APIs. Many systems, including [Google +// APIs](https://github.com/googleapis/googleapis), +// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC +// Gateway](https://github.com/grpc-ecosystem/grpc-gateway), +// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature +// and use it for large scale production services. +// +// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies +// how different portions of the gRPC request message are mapped to the URL +// path, URL query parameters, and HTTP request body. It also controls how the +// gRPC response message is mapped to the HTTP response body. `HttpRule` is +// typically specified as an `google.api.http` annotation on the gRPC method. +// +// Each mapping specifies a URL path template and an HTTP method. The path +// template may refer to one or more fields in the gRPC request message, as long +// as each field is a non-repeated field with a primitive (non-message) type. +// The path template controls how fields of the request message are mapped to +// the URL path. +// +// Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/{name=messages/*}" +// }; +// } +// } +// message GetMessageRequest { +// string name = 1; // Mapped to URL path. +// } +// message Message { +// string text = 1; // The resource content. +// } +// +// This enables an HTTP REST to gRPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` +// +// Any fields in the request message which are not bound by the path template +// automatically become HTTP query parameters if there is no HTTP request body. +// For example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get:"/v1/messages/{message_id}" +// }; +// } +// } +// message GetMessageRequest { +// message SubMessage { +// string subfield = 1; +// } +// string message_id = 1; // Mapped to URL path. +// int64 revision = 2; // Mapped to URL query parameter `revision`. +// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. +// } +// +// This enables a HTTP JSON to RPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | +// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: +// "foo"))` +// +// Note that fields which are mapped to URL query parameters must have a +// primitive type or a repeated primitive type or a non-repeated message type. +// In the case of a repeated type, the parameter can be repeated in the URL +// as `...?param=A¶m=B`. In the case of a message type, each field of the +// message is mapped to a separate parameter, such as +// `...?foo.a=A&foo.b=B&foo.c=C`. +// +// For HTTP methods that allow a request body, the `body` field +// specifies the mapping. Consider a REST update method on the +// message resource collection: +// +// service Messaging { +// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "message" +// }; +// } +// } +// message UpdateMessageRequest { +// string message_id = 1; // mapped to the URL +// Message message = 2; // mapped to the body +// } +// +// The following HTTP JSON to RPC mapping is enabled, where the +// representation of the JSON in the request body is determined by +// protos JSON encoding: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" message { text: "Hi!" })` +// +// The special name `*` can be used in the body mapping to define that +// every field not bound by the path template should be mapped to the +// request body. This enables the following alternative definition of +// the update method: +// +// service Messaging { +// rpc UpdateMessage(Message) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "*" +// }; +// } +// } +// message Message { +// string message_id = 1; +// string text = 2; +// } +// +// +// The following HTTP JSON to RPC mapping is enabled: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" text: "Hi!")` +// +// Note that when using `*` in the body mapping, it is not possible to +// have HTTP parameters, as all fields not bound by the path end in +// the body. This makes this option more rarely used in practice when +// defining REST APIs. The common usage of `*` is in custom methods +// which don't use the URL at all for transferring data. +// +// It is possible to define multiple HTTP methods for one RPC by using +// the `additional_bindings` option. Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/messages/{message_id}" +// additional_bindings { +// get: "/v1/users/{user_id}/messages/{message_id}" +// } +// }; +// } +// } +// message GetMessageRequest { +// string message_id = 1; +// string user_id = 2; +// } +// +// This enables the following two alternative HTTP JSON to RPC mappings: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` +// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: +// "123456")` +// +// ## Rules for HTTP mapping +// +// 1. Leaf request fields (recursive expansion nested messages in the request +// message) are classified into three categories: +// - Fields referred by the path template. They are passed via the URL path. +// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They are passed via the HTTP +// request body. +// - All other fields are passed via the URL query parameters, and the +// parameter name is the field path in the request message. A repeated +// field can be represented as multiple query parameters under the same +// name. +// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL query parameter, all fields +// are passed via URL path and HTTP request body. +// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP request body, all +// fields are passed via URL path and URL query parameters. +// +// ### Path template syntax +// +// Template = "/" Segments [ Verb ] ; +// Segments = Segment { "/" Segment } ; +// Segment = "*" | "**" | LITERAL | Variable ; +// Variable = "{" FieldPath [ "=" Segments ] "}" ; +// FieldPath = IDENT { "." IDENT } ; +// Verb = ":" LITERAL ; +// +// The syntax `*` matches a single URL path segment. The syntax `**` matches +// zero or more URL path segments, which must be the last part of the URL path +// except the `Verb`. +// +// The syntax `Variable` matches part of the URL path as specified by its +// template. A variable template must not contain other variables. If a variable +// matches a single path segment, its template may be omitted, e.g. `{var}` +// is equivalent to `{var=*}`. +// +// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` +// contains any reserved character, such characters should be percent-encoded +// before the matching. +// +// If a variable contains exactly one path segment, such as `"{var}"` or +// `"{var=*}"`, when such a variable is expanded into a URL path on the client +// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The +// server side does the reverse decoding. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{var}`. +// +// If a variable contains multiple path segments, such as `"{var=foo/*}"` +// or `"{var=**}"`, when such a variable is expanded into a URL path on the +// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. +// The server side does the reverse decoding, except "%2F" and "%2f" are left +// unchanged. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{+var}`. +// +// ## Using gRPC API Service Configuration +// +// gRPC API Service Configuration (service config) is a configuration language +// for configuring a gRPC service to become a user-facing product. The +// service config is simply the YAML representation of the `google.api.Service` +// proto message. +// +// As an alternative to annotating your proto file, you can configure gRPC +// transcoding in your service config YAML files. You do this by specifying a +// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same +// effect as the proto annotation. This can be particularly useful if you +// have a proto that is reused in multiple services. Note that any transcoding +// specified in the service config will override any matching transcoding +// configuration in the proto. +// +// Example: +// +// http: +// rules: +// # Selects a gRPC method and applies HttpRule to it. +// - selector: example.v1.Messaging.GetMessage +// get: /v1/messages/{message_id}/{sub.subfield} +// +// ## Special notes +// +// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the +// proto to JSON conversion must follow the [proto3 +// specification](https://developers.google.com/protocol-buffers/docs/proto3#json). +// +// While the single segment variable follows the semantics of +// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String +// Expansion, the multi segment variable **does not** follow RFC 6570 Section +// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion +// does not expand special characters like `?` and `#`, which would lead +// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding +// for multi segment variables. +// +// The path variables **must not** refer to any repeated or mapped field, +// because client libraries are not capable of handling such variable expansion. +// +// The path variables **must not** capture the leading "/" character. The reason +// is that the most common use case "{var}" does not capture the leading "/" +// character. For consistency, all path variables must share the same behavior. +// +// Repeated message fields must not be mapped to URL query parameters, because +// no client library can support such complicated mapping. +// +// If an API needs to use a JSON array for request or response body, it can map +// the request or response body to a repeated field. However, some gRPC +// Transcoding implementations may not support this feature. +message HttpRule { + // Selects a method to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax details. + string selector = 1; + + // Determines the URL pattern is matched by this rules. This pattern can be + // used with any of the {get|put|post|delete|patch} methods. A custom method + // can be defined using the 'custom' field. + oneof pattern { + // Maps to HTTP GET. Used for listing and getting information about + // resources. + string get = 2; + + // Maps to HTTP PUT. Used for replacing a resource. + string put = 3; + + // Maps to HTTP POST. Used for creating a resource or performing an action. + string post = 4; + + // Maps to HTTP DELETE. Used for deleting a resource. + string delete = 5; + + // Maps to HTTP PATCH. Used for updating a resource. + string patch = 6; + + // The custom pattern is used for specifying an HTTP method that is not + // included in the `pattern` field, such as HEAD, or "*" to leave the + // HTTP method unspecified for this rule. The wild-card rule is useful + // for services that provide content to Web (HTML) clients. + CustomHttpPattern custom = 8; + } + + // The name of the request field whose value is mapped to the HTTP request + // body, or `*` for mapping all request fields not captured by the path + // pattern to the HTTP body, or omitted for not having any HTTP request body. + // + // NOTE: the referred field must be present at the top-level of the request + // message type. + string body = 7; + + // Optional. The name of the response field whose value is mapped to the HTTP + // response body. When omitted, the entire response message will be used + // as the HTTP response body. + // + // NOTE: The referred field must be present at the top-level of the response + // message type. + string response_body = 12; + + // Additional HTTP bindings for the selector. Nested bindings must + // not contain an `additional_bindings` field themselves (that is, + // the nesting may only be one level deep). + repeated HttpRule additional_bindings = 11; +} + +// A custom pattern is used for defining custom HTTP verb. +message CustomHttpPattern { + // The name of this custom HTTP verb. + string kind = 1; + + // The path matched by this custom verb. + string path = 2; +} diff --git a/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/httpbody.proto b/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/httpbody.proto new file mode 100644 index 0000000..bc5ea44 --- /dev/null +++ b/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/httpbody.proto @@ -0,0 +1,77 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/any.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/httpbody;httpbody"; +option java_multiple_files = true; +option java_outer_classname = "HttpBodyProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Message that represents an arbitrary HTTP body. It should only be used for +// payload formats that can't be represented as JSON, such as raw binary or +// an HTML page. +// +// +// This message can be used both in streaming and non-streaming API methods in +// the request as well as the response. +// +// It can be used as a top-level request field, which is convenient if one +// wants to extract parameters from either the URL or HTTP template into the +// request fields and also want access to the raw HTTP body. +// +// Example: +// +// message GetResourceRequest { +// // A unique request id. +// string request_id = 1; +// +// // The raw HTTP body is bound to this field. +// google.api.HttpBody http_body = 2; +// } +// +// service ResourceService { +// rpc GetResource(GetResourceRequest) returns (google.api.HttpBody); +// rpc UpdateResource(google.api.HttpBody) returns +// (google.protobuf.Empty); +// } +// +// Example with streaming methods: +// +// service CaldavService { +// rpc GetCalendar(stream google.api.HttpBody) +// returns (stream google.api.HttpBody); +// rpc UpdateCalendar(stream google.api.HttpBody) +// returns (stream google.api.HttpBody); +// } +// +// Use of this type only changes how the request and response bodies are +// handled, all other features will continue to work unchanged. +message HttpBody { + // The HTTP Content-Type header value specifying the content type of the body. + string content_type = 1; + + // The HTTP request/response body as raw binary. + bytes data = 2; + + // Application specific response metadata. Must be set in the first response + // for streaming APIs. + repeated google.protobuf.Any extensions = 3; +} \ No newline at end of file diff --git a/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/source_info.proto b/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/source_info.proto new file mode 100644 index 0000000..e49658b --- /dev/null +++ b/apps/eigr_protocol/priv/protos/eigr/functions/frontend/google/api/source_info.proto @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/any.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "SourceInfoProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Source information used to create a Service Config +message SourceInfo { + // All files used during config generation. + repeated google.protobuf.Any source_files = 1; +} \ No newline at end of file diff --git a/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/action.proto b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/action.proto similarity index 87% rename from apps/cloudstate_protocol/priv/protos/protocol/cloudstate/action.proto rename to apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/action.proto index 3e0e173..b553e23 100644 --- a/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/action.proto +++ b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/action.proto @@ -1,30 +1,17 @@ -// Copyright 2019 Lightbend Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. // gRPC interface for Cloudstate Actions. syntax = "proto3"; -package cloudstate.action; +package eigr.functions.protocol.action; // Any is used so that domain events defined according to the action's business domain can be embedded inside // the protocol. import "google/protobuf/any.proto"; -import "cloudstate/entity.proto"; +import "entity.proto"; -option java_package = "io.cloudstate.protocol"; -option go_package = "github.com/cloudstateio/go-support/cloudstate/entity;entity"; +option java_package = "io.eigr.functions.protocol"; +option go_package = "github.com/eigr/go-support/eigr/entity;entity"; // An action command. // diff --git a/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/crdt.proto b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/crdt.proto similarity index 94% rename from apps/cloudstate_protocol/priv/protos/protocol/cloudstate/crdt.proto rename to apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/crdt.proto index 5c8135d..534444f 100644 --- a/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/crdt.proto +++ b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/crdt.proto @@ -16,15 +16,15 @@ syntax = "proto3"; -package cloudstate.crdt; +package eigr.functions.protocol.crdt; // Any is used so that domain events defined according to the functions business domain can be embedded inside // the protocol. import "google/protobuf/any.proto"; -import "cloudstate/entity.proto"; +import "protocol/entity.proto"; -option java_package = "io.cloudstate.protocol"; -option go_package = "cloudstate/protocol"; +option java_package = "io.eigr.functions.protocol"; +option go_package = "github.com/eigr/go-support/eigr/protocol;protocol"; // CRDT Protocol // @@ -85,10 +85,10 @@ message CrdtStreamIn { CrdtDelete deleted = 4; // A command, may be sent at any time. - Command command = 5; + eigr.functions.protocol.Command command = 5; // A stream has been cancelled. - StreamCancelled stream_cancelled = 6; + eigr.functions.protocol.StreamCancelled stream_cancelled = 6; } } @@ -102,7 +102,7 @@ message CrdtStreamOut { // A stream cancelled response, may be sent in response to stream_cancelled. CrdtStreamCancelledResponse stream_cancelled_response = 3; // A failure. Either sent in response to a command, or sent if some other error occurs. - Failure failure = 4; + eigr.functions.protocol.Failure failure = 4; } } @@ -315,9 +315,9 @@ message CrdtReply { int64 command_id = 1; - ClientAction client_action = 2; + eigr.functions.protocol.ClientAction client_action = 2; - repeated SideEffect side_effects = 4; + repeated eigr.functions.protocol.SideEffect side_effects = 4; CrdtStateAction state_action = 5; @@ -343,9 +343,9 @@ message CrdtStreamedMessage { int64 command_id = 1; - ClientAction client_action = 2; + eigr.functions.protocol.ClientAction client_action = 2; - repeated SideEffect side_effects = 3; + repeated eigr.functions.protocol.SideEffect side_effects = 3; // Indicates the stream should end, no messages may be sent for this command after this. bool end_stream = 4; @@ -354,7 +354,7 @@ message CrdtStreamedMessage { message CrdtStreamCancelledResponse { int64 command_id = 1; - repeated SideEffect side_effects = 2; + repeated eigr.functions.protocol.SideEffect side_effects = 2; CrdtStateAction state_action = 3; } diff --git a/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/entity.proto b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/entity.proto similarity index 97% rename from apps/cloudstate_protocol/priv/protos/protocol/cloudstate/entity.proto rename to apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/entity.proto index fa7faca..feee465 100644 --- a/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/entity.proto +++ b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/entity.proto @@ -16,7 +16,7 @@ syntax = "proto3"; -package cloudstate; +package eigr.functions.protocol; // Any is used so that domain events defined according to the functions business domain can be embedded inside // the protocol. @@ -24,8 +24,8 @@ import "google/protobuf/any.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/descriptor.proto"; -option java_package = "io.cloudstate.protocol"; -option go_package = "github.com/cloudstateio/go-support/cloudstate/protocol;protocol"; +option java_package = "io.eigr.functions.protocol"; +option go_package = "github.com/eigr/go-support/eigr/protocol;protocol"; // Transport-specific metadata associated with a message. // @@ -108,7 +108,7 @@ message Reply { // // If the metadata is ignored, the Cloudstate proxy MAY notify the user function by sending an error message to the // EntityDiscovery.ReportError gRPC call. - cloudstate.Metadata metadata = 2; + eigr.functions.protocol.Metadata metadata = 2; } // Forwards handling of this request to another entity. @@ -158,6 +158,9 @@ message SideEffect { // sent, or not. bool synchronous = 4; + // Send side effect to all entities of the given type. + bool broadcast = 6; + // The metadata to include with the side effect Metadata metadata = 5; } diff --git a/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/entity_key.proto b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/entity_key.proto new file mode 100644 index 0000000..cade3f5 --- /dev/null +++ b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/entity_key.proto @@ -0,0 +1,30 @@ +// Copyright 2019 Lightbend Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Extension for specifying which field in a message is to be considered an +// entity key, for the purposes associating gRPC calls with entities and +// sharding. + +syntax = "proto3"; + +import "google/protobuf/descriptor.proto"; + +package eigr.functions.protocol; + +option java_package = "io.eigr.functions.protocol"; +option go_package = "github.com/cloudstateio/go-support/eigr;eigr"; + +extend google.protobuf.FieldOptions { + bool entity_key = 1080; +} \ No newline at end of file diff --git a/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/event_sourced.proto b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/event_sourced.proto similarity index 95% rename from apps/cloudstate_protocol/priv/protos/protocol/cloudstate/event_sourced.proto rename to apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/event_sourced.proto index 0417f14..e508467 100644 --- a/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/event_sourced.proto +++ b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/event_sourced.proto @@ -16,15 +16,15 @@ syntax = "proto3"; -package cloudstate.eventsourced; +package eigr.functions.protocol.eventsourced; // Any is used so that domain events defined according to the functions business domain can be embedded inside // the protocol. import "google/protobuf/any.proto"; -import "cloudstate/entity.proto"; +import "entity.proto"; -option java_package = "io.cloudstate.protocol"; -option go_package = "cloudstate/protocol"; +option java_package = "io.eigr.functions.protocol"; +option go_package = "eigr/protocol"; // The init message. This will always be the first message sent to the entity when // it is loaded. diff --git a/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/eventing.proto b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/eventing.proto new file mode 100644 index 0000000..9fef9a0 --- /dev/null +++ b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/eventing.proto @@ -0,0 +1,76 @@ +// Copyright 2019 Lightbend Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Extension for specifying which topics a gRPC endpoint should be connected +// to, in order to facilitate consuming and producing events from a message broker. + +syntax = "proto3"; + +import "google/protobuf/descriptor.proto"; + +package eigr.functions.protocol.eventing; + +option java_package = "io.eigr.functions.protocol"; +option java_multiple_files = true; +option java_outer_classname = "EventsProto"; +option go_package = "github.com/eigr/go-support/eigr;eigr"; + +// Eventing configuration for a gRPC method. +message Eventing { + // The event source in configuration. + EventSource in = 1; + + // The event destination out configuration. + // + // Optional, if unset, messages out will not be published anywhere. + EventDestination out = 2; +} + +// Event source configuration +message EventSource { + + // The consumer group id. + // + // By default, all rpc methods on a given service with the same source will be part of the same virtual consumer + // group, messages will be routed to the different methods by type. This can be used to override that, if you want + // multiple methods to act as independent consumers of the same source (ie, if you want the same event to be + // published to each consumer) then give each consumer a unique name. + // + // Note that this does depend on the event source supporting multiple consumer groups. Queue based event sources + // may not support this. + string consumer_group = 1; + + oneof source { + + // A topic source. + // + // This will consume events from the given topic name. + string topic = 2; + + // An event log source. + // + // This will consume events from the given event log with the given persistence id. + string event_log = 3; + } +} + +message EventDestination { + oneof destination { + string topic = 1; + } +} + +extend google.protobuf.MethodOptions { + Eventing eventing = 1081; +} \ No newline at end of file diff --git a/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/value_entity.proto b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/value_entity.proto similarity index 94% rename from apps/cloudstate_protocol/priv/protos/protocol/cloudstate/value_entity.proto rename to apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/value_entity.proto index 109721c..a4fabc4 100644 --- a/apps/cloudstate_protocol/priv/protos/protocol/cloudstate/value_entity.proto +++ b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/value_entity.proto @@ -16,15 +16,15 @@ syntax = "proto3"; -package cloudstate.valueentity; +package eigr.functions.protocol.valueentity; // Any is used so that domain events defined according to the functions business domain can be embedded inside // the protocol. import "google/protobuf/any.proto"; -import "cloudstate/entity.proto"; +import "entity.proto"; -option java_package = "io.cloudstate.protocol"; -option go_package = "github.com/cloudstateio/go-support/cloudstate/entity;entity"; +option java_package = "io.eigr.functions.protocol"; +option go_package = "github.com/eigr/go-support/eigr/entity;entity"; // The Value Entity service service ValueEntity { diff --git a/apps/eigr_protocol/priv/protos/eigr/functions/proxy/grpc/reflection/v1alpha/reflection.proto b/apps/eigr_protocol/priv/protos/eigr/functions/proxy/grpc/reflection/v1alpha/reflection.proto new file mode 100644 index 0000000..462e85a --- /dev/null +++ b/apps/eigr_protocol/priv/protos/eigr/functions/proxy/grpc/reflection/v1alpha/reflection.proto @@ -0,0 +1,136 @@ +// Copyright 2016 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Service exported by server reflection + +syntax = "proto3"; + +package grpc.reflection.v1alpha; + +service ServerReflection { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + rpc ServerReflectionInfo(stream ServerReflectionRequest) + returns (stream ServerReflectionResponse); +} + +// The message sent by the client when calling ServerReflectionInfo method. +message ServerReflectionRequest { + string host = 1; + // To use reflection service, the client should set one of the following + // fields in message_request. The server distinguishes requests by their + // defined field and then handles them using corresponding methods. + oneof message_request { + // Find a proto file by the file name. + string file_by_filename = 3; + + // Find the proto file that declares the given fully-qualified symbol name. + // This field should be a fully-qualified symbol name + // (e.g. .[.] or .). + string file_containing_symbol = 4; + + // Find the proto file which defines an extension extending the given + // message type with the given field number. + ExtensionRequest file_containing_extension = 5; + + // Finds the tag numbers used by all known extensions of the given message + // type, and appends them to ExtensionNumberResponse in an undefined order. + // Its corresponding method is best-effort: it's not guaranteed that the + // reflection service will implement this method, and it's not guaranteed + // that this method will provide all extensions. Returns + // StatusCode::UNIMPLEMENTED if it's not implemented. + // This field should be a fully-qualified type name. The format is + // . + string all_extension_numbers_of_type = 6; + + // List the full names of registered services. The content will not be + // checked. + string list_services = 7; + } +} + +// The type name and extension number sent by the client when requesting +// file_containing_extension. +message ExtensionRequest { + // Fully-qualified type name. The format should be . + string containing_type = 1; + int32 extension_number = 2; +} + +// The message sent by the server to answer ServerReflectionInfo method. +message ServerReflectionResponse { + string valid_host = 1; + ServerReflectionRequest original_request = 2; + // The server set one of the following fields accroding to the message_request + // in the request. + oneof message_response { + // This message is used to answer file_by_filename, file_containing_symbol, + // file_containing_extension requests with transitive dependencies. As + // the repeated label is not allowed in oneof fields, we use a + // FileDescriptorResponse message to encapsulate the repeated fields. + // The reflection service is allowed to avoid sending FileDescriptorProtos + // that were previously sent in response to earlier requests in the stream. + FileDescriptorResponse file_descriptor_response = 4; + + // This message is used to answer all_extension_numbers_of_type requst. + ExtensionNumberResponse all_extension_numbers_response = 5; + + // This message is used to answer list_services request. + ListServiceResponse list_services_response = 6; + + // This message is used when an error occurs. + ErrorResponse error_response = 7; + } +} + +// Serialized FileDescriptorProto messages sent by the server answering +// a file_by_filename, file_containing_symbol, or file_containing_extension +// request. +message FileDescriptorResponse { + // Serialized FileDescriptorProto messages. We avoid taking a dependency on + // descriptor.proto, which uses proto2 only features, by making them opaque + // bytes instead. + repeated bytes file_descriptor_proto = 1; +} + +// A list of extension numbers sent by the server answering +// all_extension_numbers_of_type request. +message ExtensionNumberResponse { + // Full name of the base type, including the package name. The format + // is . + string base_type_name = 1; + repeated int32 extension_number = 2; +} + +// A list of ServiceResponse sent by the server answering list_services request. +message ListServiceResponse { + // The information of each service may be expanded in the future, so we use + // ServiceResponse message to encapsulate it. + repeated ServiceResponse service = 1; +} + +// The information of a single service used by ListServiceResponse to answer +// list_services request. +message ServiceResponse { + // Full name of a registered service, including its package name. The format + // is . + string name = 1; +} + +// The error code and error message sent by the server when an error occurs. +message ErrorResponse { + // This field uses the error codes defined in grpc::StatusCode. + int32 error_code = 1; + string error_message = 2; +} \ No newline at end of file diff --git a/apps/runtime/lib/protocol/middleware.ex b/apps/runtime/lib/protocol/middleware.ex index 237a695..3f26e5e 100644 --- a/apps/runtime/lib/protocol/middleware.ex +++ b/apps/runtime/lib/protocol/middleware.ex @@ -71,15 +71,22 @@ defmodule Runtime.Protocol.Middleware do require Logger alias Cloudstate.{Action.ActionResponse, SideEffect} - alias Cloudstate.Action.ActionProtocol.Stub, as: ActionClient alias Runtime.Protocol.Router - alias MassaProxy.Runtime.Grpc.Protocol.Action.Protocol, as: ActionProtocol alias Runtime @command_processor opts[:command_processor] - def start_link(%{name: name} = state) do + def child_spec(state \\ %{}) do + %{ + id: __MODULE__, + start: {__MODULE__, :start_link, [state]}, + shutdown: 60_000, + restart: :transient + } + end + + def start_link(%{entity_type: name} = state) do GenServer.start_link(__MODULE__, state, name: name) end diff --git a/apps/runtime/lib/protocol/middleware_supervisor.ex b/apps/runtime/lib/protocol/middleware_supervisor.ex new file mode 100644 index 0000000..9658a72 --- /dev/null +++ b/apps/runtime/lib/protocol/middleware_supervisor.ex @@ -0,0 +1,17 @@ +defmodule Runtime.Protocol.Middleware.Supervisor do + @moduledoc false + use Supervisor + + def start_link(args \\ %{}) do + Supervisor.start_link(__MODULE__, args, name: __MODULE__) + end + + @impl true + def init(_args) do + children = [ + Runtime.Entity.EntityRegistry.child_spec(%{}) + ] + + Supervisor.init(children, strategy: :one_for_one) + end +end diff --git a/apps/runtime/lib/runtime.ex b/apps/runtime/lib/runtime.ex index 393463f..1241856 100644 --- a/apps/runtime/lib/runtime.ex +++ b/apps/runtime/lib/runtime.ex @@ -2,19 +2,68 @@ defmodule Runtime do @moduledoc """ `Runtime`. """ - use Application + use Supervisor + + alias Runtime.Protocol.Middleware + + defmodule MiddlewareDefinition do + defstruct entity_type: nil, module: nil + + @type t(entity_type, module) :: %MiddlewareDefinition{ + entity_type: entity_type, + module: module + } + + @type t :: %MiddlewareDefinition{entity_type: String.t(), module: module()} + end + + defmodule State do + defstruct middlewares: [] + + @type t(middlewares) :: %State{middlewares: middlewares} + + @type t :: %State{middlewares: list(%MiddlewareDefinition{})} + end + + @spec start_link(State.t()) :: :ignore | {:error, any} | {:ok, pid} + def start_link(state \\ %{}) do + Supervisor.start_link(__MODULE__, state, name: __MODULE__) + end @impl true - def start(_type, _args) do - children = - [ - {Task.Supervisor, name: ProxyRuntime.TaskSupervisor}, - {Runtime.Entity.EntityRegistry.Supervisor, [%{}]} - ] - |> Stream.reject(&is_nil/1) - |> Enum.to_list() - - opts = [strategy: :one_for_one, name: ProxyRuntime.Supervisor] - Supervisor.start_link(children, opts) + def init(%State{middlewares: middlewares} = _state) do + Enum.map(middlewares, fn %MiddlewareDefinition{entity_type: type, module: _module} = + _middleware -> + _process_name = get_name(type) + end) + + children = [ + Runtime.Entity.EntityRegistry.child_spec(%{}) + ] + + Supervisor.init(children, strategy: :one_for_one) + end + + # @impl true + # def start(_type, _args) do + # children = + # [ + # {Task.Supervisor, name: ProxyRuntime.TaskSupervisor}, + # {Runtime.Entity.EntityRegistry.Supervisor, [%{}]} + # ] + # |> Stream.reject(&is_nil/1) + # |> Enum.to_list() + + # opts = [strategy: :one_for_one, name: ProxyRuntime.Supervisor] + # Supervisor.start_link(children, opts) + # end + + defp get_name(entity_type) do + mod = + entity_type + |> String.split(".") + |> Enum.at(-1) + + Module.concat(Middleware, mod) end end diff --git a/apps/runtime_grpc/lib/protocol/action/action_middleware.ex b/apps/runtime_grpc/lib/protocol/action/action_middleware.ex index db24791..1d59123 100644 --- a/apps/runtime_grpc/lib/protocol/action/action_middleware.ex +++ b/apps/runtime_grpc/lib/protocol/action/action_middleware.ex @@ -1,5 +1,6 @@ defmodule Runtime.GRPC.Protocol.Action.Middleware do - use Runtime.Protocol.Middleware, command_processor: Runtime.Protocol.Action.Processor + use Runtime.Protocol.Middleware, + command_processor: Runtime.GRPC.Protocol.Action.Processor alias Cloudstate.Action.ActionProtocol.Stub, as: ActionClient alias Runtime.GRPC.Protocol.Action.Protocol, as: ActionProtocol diff --git a/apps/runtime_grpc/lib/protocol/action/processor.ex b/apps/runtime_grpc/lib/protocol/action/action_processor.ex similarity index 100% rename from apps/runtime_grpc/lib/protocol/action/processor.ex rename to apps/runtime_grpc/lib/protocol/action/action_processor.ex diff --git a/apps/runtime_grpc/lib/protocol/action/protocol.ex b/apps/runtime_grpc/lib/protocol/action/action_protocol.ex similarity index 100% rename from apps/runtime_grpc/lib/protocol/action/protocol.ex rename to apps/runtime_grpc/lib/protocol/action/action_protocol.ex From f3f01180acbeb8cef91c1f39af333352bd2682ff Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Fri, 15 Apr 2022 12:10:03 -0300 Subject: [PATCH 18/19] A simple proposal to provide the invocation capabilities of services without having to appeal to Forwards --- .../functions/protocol/eigr/invoker.proto | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/invoker.proto diff --git a/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/invoker.proto b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/invoker.proto new file mode 100644 index 0000000..6c9ef94 --- /dev/null +++ b/apps/eigr_protocol/priv/protos/eigr/functions/protocol/eigr/invoker.proto @@ -0,0 +1,55 @@ +// gRPC interface for invokable services. + +syntax = "proto3"; + +package eigr.functions.protocol; + +import "google/protobuf/any.proto"; +import "entity.proto"; + +option java_package = "io.eigr.functions.protocol"; +option go_package = "github.com/eigr/go-support/eigr/protocol;protocol"; + +message Error { + string message = 1; +} + +message Request { + // The name of the service to forward to. + string service_name = 1; + + // The name of the command. + string command_name = 2; + + // The payload. + google.protobuf.Any payload = 3; + + // The metadata to include with the forward + Metadata metadata = 4; + +} + +// The response sent by the remote service to the caller. +message Response { + + // An entity might return some useful information or it might return an error. + oneof result { + // The result of the function call. + google.protobuf.Any payload = 1; + + // The error returned by the remote service. + Error error = 2; + } + + // Metadata for the reply + Metadata metadata = 3; + +} + +// Invocation service. +service ServiceInvoker { + + // Send something to another entity and wait for their response. + rpc Invoke(Request) returns (Response) {} + +} \ No newline at end of file From 6a9e102567ba0de95e1e0267631f5c61f587955f Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Fri, 20 May 2022 14:03:10 -0300 Subject: [PATCH 19/19] Merge --- apps/eventing/mix.exs | 4 +--- apps/massa_proxy/lib/supervisor.ex | 14 +++++++++++--- .../lib/protocol/middleware_supervisor.ex | 17 ----------------- apps/runtime/lib/runtime.ex | 17 ++++++++++------- 4 files changed, 22 insertions(+), 30 deletions(-) delete mode 100644 apps/runtime/lib/protocol/middleware_supervisor.ex diff --git a/apps/eventing/mix.exs b/apps/eventing/mix.exs index 422b7bc..4b6ea3d 100644 --- a/apps/eventing/mix.exs +++ b/apps/eventing/mix.exs @@ -25,9 +25,7 @@ defmodule Eventing.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ - # {:dep_from_hexpm, "~> 0.3.0"}, - # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}, - # {:sibling_app_in_umbrella, in_umbrella: true} + {:cloudevents, "~> 0.4.0"} ] end end diff --git a/apps/massa_proxy/lib/supervisor.ex b/apps/massa_proxy/lib/supervisor.ex index fa46833..6f915c5 100644 --- a/apps/massa_proxy/lib/supervisor.ex +++ b/apps/massa_proxy/lib/supervisor.ex @@ -2,6 +2,9 @@ defmodule MassaProxy.Children do @moduledoc false use Supervisor + alias Runtime + alias Runtime.{MiddlewareDefinition, State} + require Logger def start_link(config) do @@ -10,13 +13,20 @@ defmodule MassaProxy.Children do @impl true def init(config) do - children = [ + children = mount_supervisor_tree(config) + + Supervisor.init(children, strategy: :one_for_one) + end + + defp mount_supervisor_tree(config) do + [ http_server(config), {Registry, [name: MassaProxy.LocalRegistry, keys: :unique]}, {DynamicSupervisor, [name: MassaProxy.LocalSupervisor, strategy: :one_for_one]}, {DynamicSupervisor, [name: MassaProxy.Runtime.MiddlewareSupervisor, strategy: :one_for_one]}, {MassaProxy.Infra.Cache.Distributed, []}, + # {Runtime, %State{middlewares: [%MiddlewareDefinition{}]}} local_node(), %{ id: CachedServers, @@ -27,8 +37,6 @@ defmodule MassaProxy.Children do start: {MassaProxy.Infra.Cache, :start_link, [[cache_name: :reflection_cache]]} } ] - - Supervisor.init(children, strategy: :one_for_one) end defp http_server(config) do diff --git a/apps/runtime/lib/protocol/middleware_supervisor.ex b/apps/runtime/lib/protocol/middleware_supervisor.ex deleted file mode 100644 index 9658a72..0000000 --- a/apps/runtime/lib/protocol/middleware_supervisor.ex +++ /dev/null @@ -1,17 +0,0 @@ -defmodule Runtime.Protocol.Middleware.Supervisor do - @moduledoc false - use Supervisor - - def start_link(args \\ %{}) do - Supervisor.start_link(__MODULE__, args, name: __MODULE__) - end - - @impl true - def init(_args) do - children = [ - Runtime.Entity.EntityRegistry.child_spec(%{}) - ] - - Supervisor.init(children, strategy: :one_for_one) - end -end diff --git a/apps/runtime/lib/runtime.ex b/apps/runtime/lib/runtime.ex index 1241856..0e5ce44 100644 --- a/apps/runtime/lib/runtime.ex +++ b/apps/runtime/lib/runtime.ex @@ -32,14 +32,17 @@ defmodule Runtime do @impl true def init(%State{middlewares: middlewares} = _state) do - Enum.map(middlewares, fn %MiddlewareDefinition{entity_type: type, module: _module} = - _middleware -> - _process_name = get_name(type) - end) + middleware_children = + Enum.map(middlewares, fn %MiddlewareDefinition{entity_type: type, module: module} = + _middleware -> + process_name = get_name(type) + module.child_spec(process_name) + end) - children = [ - Runtime.Entity.EntityRegistry.child_spec(%{}) - ] + children = + [ + Runtime.Entity.EntityRegistry.child_spec(%{}) + ] ++ middleware_children Supervisor.init(children, strategy: :one_for_one) end