This module defines the riak_api_pb_service behaviour.
Required callback functions: init/0, decode/2, encode/1, process/2, process_stream/3.
Encapsulates the behaviour and registration of application-specific interfaces exposed over the Protocol Buffers API. Service modules should implement the behaviour, and the host applications should register them on startup like so:
%% Register a single range of message codes to the foo service
ok = riak_api_pb_service:register(foo, 101, 102),
%% Register multiple services at once
ok = riak_api_pb_service:register([{bar, 200, 210},
{baz, 211, 214}]).
On shutdown, host applications should deregister services they
registered on startup. The same arguments as were sent to
register/1,2,3 are valid arguments to deregister/1,2,3.
%% Deregister all my services
ok = riak_api_pb_service:deregister([{foo, 101, 102},
{bar, 200, 210},
{baz, 211, 214}]).
Service modules must export five callbacks:
init() ->
State.
State = term()
The init/0 callback is called to create any state that the
service may need to operate. The return value of this callback will
be passed to the service in other callbacks.
decode(Code, Message) ->
{ok, DecodedMessage} |
{ok, DecodedMessage, PermAndTarget} |
{error, Reason}.
Code = non_neg_integer()
Message = binary()
DecodedMessage = Reason = term()
PermAndTarget = perm_and_target()
The decode/2 callback is handed a message code and wire message
that is registered to this service and should decode it into an
Erlang term that can be handled by the process/2 callback. If the
message does not decode properly, it should return an error tuple
with an appropriate reason. The decoded message may optionally
include a permission and target tuple used by the security system
to restrict access to the operation. Most services will simply
delegate encoding to the riak_pb application.
encode(Message) ->
{ok, EncodedMessage} |
Error.
Message = Error = term()
EncodedMessage = iodata()
The encode/1 callback is given an Erlang term that is a reply
message to a client and should encode that message as iodata,
including an appropriate message code on the head. Any return value
other than {ok, iodata()} will be interpreted as an error. Again,
most services will simply delegate encoding to the riak_pb
application.
process(Message, State) ->
{reply, ReplyMessage, NewState} |
{reply, {stream, ReqId}, NewState} |
{error, Error, NewState}.
Message = State = ReqId = ReplyMessage = NewState = term()
Error = iodata() | {format, term()} | {format, io:format(), [term()]}
The process/2 callback is where the work of servicing a client
request is done. The return value of the decode/2 callback will
be passed as Message and the last value of the service state as
State (as returned from init/0 or a previous invocation of
process/2 or process_stream/3). The callback should return
3-tuples, any of which include the modified service state as the
last entry. The first form is a simple reply in which a single
message is returned to the client (passing through encode/1 along
the way). The second form moves the service into streaming mode,
using the returned ReqId (see process_stream/3).
The third form replies with an error to the client, the second
entry (Error) becoming the errmsg field of the rpberrorresp
message. If it is iodata, it will be passed verbatim to the client.
If it is the format 2-tuple, it will be formatted with the "~p"
format string before being sent to the client. If it is the
format 3-tuple, the list of terms will be formatted against the
format string before being sent to the client.
process_stream(Message, ReqId, State) ->
{reply, Reply, NewState} |
{ignore, NewState} |
{done, Reply, NewState} |
{done, NewState} |
{error, Error, NewState}.
Message = ReqId = State = NewState = term()
Reply = [ term() ] | term()
Error = iodata() | {format, term()} | {format, io:format(), [term()]}
The process_stream/3 callback is invoked when the socket/server
process receives a message from another Erlang process while in
streaming mode. The passed ReqId is the value returned from
process/2 when streaming mode was started, and is usually used to
identify or ignore incoming messages from other processes. Like
process/2, the state of the service is passed as the last
argument.
process/2, the last entry of all return-value tuples
should be the updated state of the service. Also, similarly to
process/2, a reply tuple will result in sending a normal
message to the client. When Reply is a list, this will be
interpreted as sending multiple messages to the client in one pass.
Error tuples have similar semantics to process/2, but will also
cause the service to exit streaming mode. The ignore tuple will
cause the server to do nothing. The done tuples have the same
semantics as reply (including multi-message replies) and ignore
but signal a normal end of the streaming operation.
registration() = {Service::module(), MinCode::pos_integer(), MaxCode::pos_integer()}
| deregister/1 | Removes the registration of a number of services modules at once. |
| deregister/2 | Removes the registration of a previously-registered service module. |
| deregister/3 | Removes the registration of a previously-registered service module. |
| register/1 | Registers a number of services at once. |
| register/2 | Registers a service module for a given message code. |
| register/3 | Registers a service module for a given range of message codes. |
| swap/3 | Perform an atomic swap of current module to NewModule for
the given code range. |
deregister(List::[registration()]) -> ok | {error, Reason::term()}
Removes the registration of a number of services modules at once.
See also: deregister/3.
deregister(Module::module(), Code::pos_integer()) -> ok | {error, Err::term()}
Removes the registration of a previously-registered service module. Inputs will be validated such that the registered module must match the one being removed.
deregister(Module::module(), MinCode::pos_integer(), MaxCode::pos_integer()) -> ok | {error, Err::term()}
Removes the registration of a previously-registered service module.
See also: deregister/2.
register(List::[registration()]) -> ok | {error, Reason::term()}
Registers a number of services at once.
See also: register/3.
register(Module::module(), Code::pos_integer()) -> ok | {error, Err::term()}
Equivalent to register(Module, Code, Code).
Registers a service module for a given message code.
See also: register/3.
register(Module::module(), MinCode::pos_integer(), MaxCode::pos_integer()) -> ok | {error, Err::term()}
Registers a service module for a given range of message codes. The service module must implement the behaviour and be able to decode and process messages for the given range of message codes. Service modules should be registered before the riak_api application starts.
swap(NewModule::module(), MinCode::pos_integer(), MaxCode::pos_integer()) -> ok | {error, Err::term()}
Perform an atomic swap of current module to NewModule for
the given code range. The code range must exactly match an
existing range. Otherwise an error is returned.
Generated by EDoc