macula_request behaviour (macula v11.1.0)
View SourceBehaviour for supervised RPC requests.
call/5 is a plain blocking call in the caller's own process — there is no addressable pid to cancel it from outside. This is the consumer-side counterpart to macula_response: start_link/6,7 returns immediately with a pid, runs macula:call/5 in a linked worker, delivers the outcome to Module:handle_reply/2, and publishes rpc.sent_v1 / rpc.completed_v1 mesh facts around the request — including outcome => cancelled if the request is cancelled before a reply arrives.
Call and publish functions
start_link/8 takes call, the function the request calls with, macula:call/5 by default. start_link_direct/8 takes direct_call, macula_direct_dial:call/6 by default, which gets the other options. Both take fact_publish, the function the request announces its facts with, macula:publish/4 by default. A test gives its own functions this way instead of replacing a module.
Example
-module(add_caller).
-behaviour(macula_request).
-export([init/1, handle_reply/2]).
init(Parent) -> {ok, Parent}.
handle_reply(Result, Parent) ->
Parent ! {add_result, Result},
{stop, normal, Parent}. {ok, Pid} = macula_request:start_link(add_caller, Pool, Realm,
<<"math.add_v1">>, #{a => 2, b => 3}, 30_000, self()).Direct-dial
Both starts reach a provider the same way. macula:call/5 resolves the procedure's procedure_advertisement from the DHT (published by macula_response:advertise_direct/6 on the provider side), resolves that record's serving_station to a dialable endpoint via the station's own station_endpoint record (every macula-station publishes its own automatically), and calls the advertised provider there in one hop via macula:call_station/8. start_link_direct also hands its options to that resolution. Requires the provider to have advertised via advertise_direct/6, not plain advertise/5: a plain advertise publishes no discoverable record.
Summary
Functions
Cancel an in-flight request. Publishes rpc.completed_v1 with outcome => cancelled if no reply had arrived yet.
Start a request. Calls Procedure on (Pool, Realm) with Payload, timing out after TimeoutMs; Args is passed to Module:init/1.
As start_link/6, with Args passed to Module:init/1.
As start_link/7, with options: call and fact_publish give the functions the request calls and announces with (see "Call and publish functions" above).
As start_link/6, but resolves and dials the serving station directly instead of routing through the pool's existing links. See the "Direct-dial" section above.
As start_link_direct/6, with Args passed to Module:init/1.
As start_link_direct/7, with options: direct_call and fact_publish give the functions the request calls and announces with (see "Call and publish functions" above), and the other options go to the call as macula_direct_dial:call/6 takes them. An org namespaced procedure's authorization is checked against the realm key the pool pinned (see macula_direct_dial's module doc, "Trust model").
Types
-type call() :: fun((macula:pool(), macula:realm(), macula:procedure(), term(), pos_integer()) -> {ok, term()} | {error, term()}).
-type direct_call() :: fun((macula:pool(), macula:realm(), macula:procedure(), term(), pos_integer(), map()) -> {ok, term()} | {error, term()}).
-type direct_opts() :: #{direct_call => direct_call(), fact_publish => macula_lifetime_announcer:publish(), atom() => term()}.
-type start_opts() :: #{call => call(), fact_publish => macula_lifetime_announcer:publish()}.
Callbacks
Functions
-spec cancel(pid()) -> ok.
Cancel an in-flight request. Publishes rpc.completed_v1 with outcome => cancelled if no reply had arrived yet.
-spec start_link(module(), macula:pool(), macula:realm(), macula:procedure(), term(), 1..600000) -> {ok, pid()} | {error, term()}.
Start a request. Calls Procedure on (Pool, Realm) with Payload, timing out after TimeoutMs; Args is passed to Module:init/1.
-spec start_link(module(), macula:pool(), macula:realm(), macula:procedure(), term(), 1..600000, term()) -> {ok, pid()} | {error, term()}.
As start_link/6, with Args passed to Module:init/1.
-spec start_link(module(), macula:pool(), macula:realm(), macula:procedure(), term(), 1..600000, term(), start_opts()) -> {ok, pid()} | {error, term()}.
As start_link/7, with options: call and fact_publish give the functions the request calls and announces with (see "Call and publish functions" above).
-spec start_link_direct(module(), macula:pool(), macula:realm(), macula:procedure(), term(), 1..600000) -> {ok, pid()} | {error, term()}.
As start_link/6, but resolves and dials the serving station directly instead of routing through the pool's existing links. See the "Direct-dial" section above.
-spec start_link_direct(module(), macula:pool(), macula:realm(), macula:procedure(), term(), 1..600000, term()) -> {ok, pid()} | {error, term()}.
As start_link_direct/6, with Args passed to Module:init/1.
-spec start_link_direct(module(), macula:pool(), macula:realm(), macula:procedure(), term(), 1..600000, term(), direct_opts()) -> {ok, pid()} | {error, term()}.
As start_link_direct/7, with options: direct_call and fact_publish give the functions the request calls and announces with (see "Call and publish functions" above), and the other options go to the call as macula_direct_dial:call/6 takes them. An org namespaced procedure's authorization is checked against the realm key the pool pinned (see macula_direct_dial's module doc, "Trust model").