%% ------------------------------------------------------------------- %% %% Copyright (c) 2018 Christopher S. Meiklejohn. All Rights Reserved. %% Copyright (c) 2022 Alejandro M. Ramallo. All Rights Reserved. %% %% This file is provided to you 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. %% %% ------------------------------------------------------------------- -module(partisan_rpc). -include("partisan.hrl"). -type error_reason() :: timeout | any(). %% API -export([call/4]). -export([call/5]). -export([prepare_opts/1]). -dialyzer([{nowarn_function, call/4}, no_return]). -dialyzer([{nowarn_function, call/5}, no_return]). %% ============================================================================= %% API %% ============================================================================= %% ----------------------------------------------------------------------------- %% @doc %% @end %% ----------------------------------------------------------------------------- -spec call( Node :: node(), Module :: module(), Function :: atom(), Arguments :: [any()]) -> Reply :: any() | {badrpc, error_reason()}. call(Node, Module, Function, Arguments) -> call(Node, Module, Function, Arguments, infinity). %% ----------------------------------------------------------------------------- %% @doc %% @end %% ----------------------------------------------------------------------------- -spec call( Node :: node(), Module :: module(), Function :: atom(), Arguments :: [any()], Timeout :: timeout() | partisan_peer_service_manager:forward_opts()) -> Reply :: any() | {badrpc, error_reason()}. call(Node, Module, Function, Arguments, Timeout) when ?IS_VALID_TMO(Timeout) -> call(Node, Module, Function, Arguments, #{timeout => Timeout}); call(Node, Module, Function, Arguments, Opts0) -> Self = partisan:self(), Timeout = maps:get(timeout, Opts0, ?DEFAULT_TIMEOUT), ?IS_VALID_TMO(Timeout) orelse error({?MODULE, badarg}), Opts = prepare_opts( partisan_config:get(forward_options, maps:without([timeout], Opts0)) ), Msg = {call, Module, Function, Arguments, Timeout, {origin, Self}}, partisan:forward_message(Node, partisan_rpc_backend, Msg, Opts), receive {rpc_response, Response} -> Response after Timeout -> {badrpc, timeout} end. %% ----------------------------------------------------------------------------- %% @doc %% @end %% ----------------------------------------------------------------------------- -spec prepare_opts(list() | map()) -> map(). prepare_opts(L) when is_list(L) -> prepare_opts(maps:from_list(L)); prepare_opts(#{channel := _} = Opts) -> Opts; prepare_opts(Opts) when is_map(Opts) -> Opts#{channel => rpc_channel()}. %% ============================================================================= %% PRIVATE %% ============================================================================= rpc_channel() -> case maps:find(?RPC_CHANNEL, partisan_config:get(channels)) of {ok, _} -> ?RPC_CHANNEL; error -> ?DEFAULT_CHANNEL end.