Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit.

* Factored out server processes from request/response processing.
* Allow req/res processors to register themselves as riak_api_pb_service behaviours.
  • Loading branch information...
commit fc3ea8caa9784e5da72c50074a39e351791a433a 0 parents
Sean Cribbs seancribbs authored
7 .gitignore
@@ -0,0 +1,7 @@
+.eunit/*
+deps/*
+priv/*
+*.o
+*.beam
+doc
+ebin
33 README.md
@@ -0,0 +1,33 @@
+# `riak_api` - Riak Client APIs
+
+This OTP application encapsulates services for presenting Riak's
+public-facing interfaces. Currently this means a generic interface for
+exposing Protocol Buffers-based services; HTTP services via Webmachine
+will be moved here at a later time.
+
+## Contributing
+
+We encourage contributions to `riak_api` from the community.
+
+1. Fork the [`riak_api`](https://github.com/basho/riak_api) repository
+ on Github.
+2. Clone your fork or add the remote if you already have a clone of
+ the repository.
+ ```shell
+ git clone git@github.com:yourusername/riak_kv.git
+ # or
+ git remote add mine git@github.com:yourusername/riak_kv.git
+ ```
+3. Create a topic branch for your change.
+ ```shell
+ git checkout -b some-topic-branch
+ ```
+4. Make your change and commit. Use a clear and descriptive commit
+ message, spanning multiple lines if detailed explanation is needed.
+5. Push to your fork of the repository and then send a pull-request
+ through Github.
+ ```shell
+ git push mine some-topic-branch
+ ```
+6. A Basho engineer or community maintainer will review your patch and
+ merge it into the main repository or send you feedback.
7 rebar.config
@@ -0,0 +1,7 @@
+{erl_opts, [warnings_as_errors, {parse_transform, lager_transform}]}.
+
+{deps, [
+ {lager, ".*", {git, "git://github.com/basho/lager.git", "master"}},
+ {riakc, ".*", {git, "git://github.com/basho/riak-erlang-client.git", "master"}},
+ {riak_core, ".*", {git, "git://github.com/basho/riak_core.git", "master"}}
+ ]}.
16 src/riak_api.app.src
@@ -0,0 +1,16 @@
+%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+{application, riak_api,
+ [
+ {description, "Riak Client APIs"},
+ {vsn, "1.0.0"},
+ {applications, [
+ kernel,
+ stdlib,
+ sasl
+ ]},
+ {registered, []},
+ {mod, {riak_api_app, []}},
+ {env, [
+ ]}
+]}.
54 src/riak_api_app.erl
@@ -0,0 +1,54 @@
+%% -------------------------------------------------------------------
+%%
+%% riak_api_app: Riak Client APIs
+%%
+%% Copyright (c) 2007-2010 Basho Technologies, Inc. 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.
+%%
+%% -------------------------------------------------------------------
+
+%% @doc Bootstrapping the Riak Client APIs application.
+-module(riak_api_app).
+
+-behaviour(application).
+-export([start/2,
+ stop/1]).
+
+%% @doc The application:start callback.
+-spec start(Type::application:start_type(), StartArgs::term())
+ -> {ok, Pid::pid()} | ignore | {error, Error::term()}.
+start(_Type, _StartArgs) ->
+ riak_core_util:start_app_deps(riak_api),
+
+ %% TODO: cluster_info registration. What do we expose?
+ %% catch cluster_info:register_app(riak_api_cinfo),
+
+ case riak_api_sup:start_link() of
+ {ok, Pid} ->
+ %% TODO: Is it necessary to register the service? We might
+ %% want to use the registration to cause service_up events
+ %% and then propagate config information for client
+ %% auto-config.
+ %% riak_core:register(riak_api, []),
+ {ok, Pid};
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+%% @doc The application:stop callback.
+-spec stop(State::term()) -> ok.
+stop(_State) ->
+ ok.
93 src/riak_api_pb_listener.erl
@@ -0,0 +1,93 @@
+%% -------------------------------------------------------------------
+%%
+%% riak_api_pb_listener: Listen for protocol buffer clients
+%%
+%% Copyright (c) 2007-2010 Basho Technologies, Inc. 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.
+%%
+%% -------------------------------------------------------------------
+
+%% @doc entry point for TCP-based protocol buffers service
+
+-module(riak_api_pb_listener).
+-behaviour(gen_nb_server).
+-export([start_link/0]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+-export([sock_opts/0, new_connection/2]).
+-record(state, {portnum}).
+
+%% @doc Starts the PB listener
+-spec start_link() -> {ok, pid()} | {error, term()}.
+start_link() ->
+ PortNum = app_helper:get_env(riak_api, pb_port),
+ IpAddr = app_helper:get_env(riak_api, pb_ip),
+ gen_nb_server:start_link(?MODULE, IpAddr, PortNum, [PortNum]).
+
+%% @doc Initialization callback for gen_nb_server.
+-spec init(list()) -> {ok, #state{}}.
+init([PortNum]) ->
+ {ok, #state{portnum=PortNum}}.
+
+%% @doc Preferred socket options for the listener.
+-spec sock_opts() -> [gen_tcp:option()].
+sock_opts() ->
+ BackLog = app_helper:get_env(riak_api, pb_backlog, 5),
+ NoDelay = app_helper:get_env(riak_api, disable_pb_nagle, true),
+ [binary, {packet, 4}, {reuseaddr, true}, {backlog, BackLog}, {nodelay, NoDelay}].
+
+%% @doc The handle_call/3 gen_nb_server callback. Unused.
+-spec handle_call(term(), pid(), #state{}) -> {reply, term(), #state{}}.
+handle_call(_Req, _From, State) ->
+ {reply, not_implemented, State}.
+
+%% @doc The handle_cast/2 gen_nb_server callback. Unused.
+-spec handle_cast(term(), #state{}) -> {noreply, #state{}}.
+handle_cast(_Msg, State) -> {noreply, State}.
+
+%% @doc The handle_info/2 gen_nb_server callback. Unused.
+-spec handle_info(term(), #state{}) -> {noreply, #state{}}.
+handle_info(_Info, State) -> {noreply, State}.
+
+%% @doc The code_change/3 gen_nb_server callback. Unused.
+-spec terminate(Reason, State) -> ok when
+ Reason :: normal | shutdown | {shutdown,term()} | term(),
+ State :: #state{}.
+terminate(_Reason, _State) ->
+ %% TODO: Update with Russell's new stats system
+ %% riak_kv_stat:update(pbc_disconnect),
+ ok.
+
+%% @doc The gen_server code_change/3 callback, called when performing
+%% a hot code upgrade on the server. Currently unused.
+-spec code_change(OldVsn, State, Extra) -> {ok, State} | {error, Reason}
+ when
+ OldVsn :: Vsn | {down, Vsn},
+ Vsn :: term(),
+ State :: #state{},
+ Extra :: term(),
+ Reason :: term().
+code_change(_OldVsn, State, _Extra) -> {ok, State}.
+
+%% @doc The connection initiation callback for gen_nb_server, called
+%% when a new socket is accepted.
+-spec new_connection(gen_tcp:socket(), #state{}) -> {ok, #state{}}.
+new_connection(Socket, State) ->
+ {ok, Pid} = riak_api_pb_socket_sup:start_socket(),
+ ok = gen_tcp:controlling_process(Socket, Pid),
+ ok = riak_api_pb_socket:set_socket(Pid, Socket),
+ {ok, State}.
+
202 src/riak_api_pb_server.erl
@@ -0,0 +1,202 @@
+%% -------------------------------------------------------------------
+%%
+%% riak_kv_pb_socket: service protocol buffer clients
+%%
+%% Copyright (c) 2007-2010 Basho Technologies, Inc. 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.
+%%
+%% -------------------------------------------------------------------
+
+%% @doc Service protocol buffer clients. This module implements only
+%% the TCP socket management and dispatch of incoming messages to
+%% service modules.
+
+-module(riak_api_pb_server).
+
+-ifdef(TEST).
+-include_lib("eunit/include/eunit.hrl").
+-endif.
+
+-behaviour(gen_server).
+
+-export([start_link/0, set_socket/2]).
+
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-record(state, {
+ socket :: port(), % socket
+ req, % current request
+ dispatch :: dict(), % dispatch table of msg code -> service
+ states :: dict() % per-service connection state
+ }).
+
+%% ===================================================================
+%% Public API
+%% ===================================================================
+
+%% @doc Starts a PB server, ready to service a single socket.
+-spec start_link() -> {ok, pid()} | {error, term()}.
+start_link() ->
+ gen_server:start_link(?MODULE, [], []).
+
+%% @doc Sets the socket to service for this server.
+-spec set_socket(pid(), gen_tcp:socket()) -> ok.
+set_socket(Pid, Socket) ->
+ gen_server:call(Pid, {set_socket, Socket}, infinity).
+
+%% @doc The gen_server init/1 callback, initializes the
+%% riak_api_pb_server.
+-spec init(list()) -> {ok, #state{}}.
+init([]) ->
+ %% TODO: use Russell's new stats system
+ %% riak_kv_stat:update(pbc_connect)
+ Dispatch = riak_api_pb_service:dispatch_table(),
+ ServiceStates = lists:foldl(fun(Service, States) ->
+ dict:store(Service, Service:init(), States)
+ end,
+ dict:new(), riak_api_pb_service:services()),
+ {ok, #state{dispatch=Dispatch,
+ states=ServiceStates}}.
+
+%% @doc The handle_call/3 gen_server callback.
+-spec handle_call(Message::term(), From::pid(), State::#state{}) -> {reply, Message::term(), NewState::#state{}}.
+handle_call({set_socket, Socket}, _From, State) ->
+ inet:setopts(Socket, [{active, once}, {packet, 4}, {header, 1}]),
+ {reply, ok, State#state{socket = Socket}}.
+
+%% @doc The handle_cast/2 gen_server callback.
+-spec handle_cast(Message::term(), State::#state{}) -> {noreply, NewState::#state{}}.
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+%% @doc The handle_info/2 gen_server callback.
+-spec handle_info(Message::term(), State::#state{}) -> {noreply, NewState::#state{}} | {stop, Reason::atom(), NewState::#state{}}.
+handle_info({Ref, done}, #state{req={_Service,Ref}}=State) ->
+ %% Streaming requests set the req reference.
+ {noreply, State#state{req=undefined}};
+handle_info({Ref, {MessageCode, Message}}, #state{req={Service,Ref}}=State) ->
+ {ok, Encoded} = Service:encode(MessageCode, Message),
+ send_message(Encoded, State),
+ {noreply, State};
+handle_info({tcp_closed, Socket}, State=#state{socket=Socket}) ->
+ {stop, normal, State};
+handle_info({tcp_error, Socket, _Reason}, State=#state{socket=Socket}) ->
+ {stop, normal, State};
+handle_info({tcp, _Sock, [MsgCode|MsgData]}, State=#state{
+ socket=Socket,
+ req=undefined,
+ dispatch=Dispatch,
+ states=ServiceStates}) ->
+ %% First find the appropriate service module to dispatch
+ case dict:find(MsgCode, Dispatch) of
+ {ok, Service} ->
+ %% Decode the message according to the service
+ case Service:decode(MsgCode, MsgData) of
+ {ok, Message} ->
+ %% Process the message
+ ServiceState = dict:fetch(Service, ServiceStates),
+ NewState = process_message(Service, Message, ServiceState, State);
+ {error, Reason} ->
+ send_error("Message decoding error: ~p", [Reason], State),
+ NewState = State
+ end;
+ error ->
+ send_error("Unknown message code.", State),
+ NewState = State
+ end,
+ inet:setopts(Socket, [{active, once}]),
+ {noreply, NewState};
+handle_info({tcp, _Sock, _Data}, State) ->
+ %% req =/= undefined: received a new request while another was in
+ %% progress -> Error
+ lager:error("Received a new PB socket request"
+ " while another was in progress"),
+ send_error("Cannot send another request while one is in progress", State),
+ {stop, normal, State}.
+
+
+%% @doc The gen_server terminate/2 callback, called when shutting down
+%% the server.
+-spec terminate(Reason, State) -> ok when
+ Reason :: normal | shutdown | {shutdown,term()} | term(),
+ State :: #state{}.
+terminate(_Reason, _State) ->
+ %% TODO: Update with Russell's new stats system
+ %% riak_kv_stat:update(pbc_disconnect),
+ ok.
+
+%% @doc The gen_server code_change/3 callback, called when performing
+%% a hot code upgrade on the server. Currently unused.
+-spec code_change(OldVsn, State, Extra) -> {ok, State} | {error, Reason} when
+ OldVsn :: Vsn | {down, Vsn},
+ Vsn :: term(),
+ State :: #state{},
+ Extra :: term(),
+ Reason :: term().
+code_change(_OldVsn,State,_Extra) ->
+ {ok, State}.
+
+%% ===================================================================
+%% Internal functions
+%% ===================================================================
+
+%% @doc Dispatches an incoming message to the registered service that
+%% recognizes it. This is called after the message has been identified
+%% and decoded.
+-spec process_message(atom(), term(), term(), #state{}) -> #state{}.
+process_message(Service, Message, ServiceState, #state{states=ServiceStates}=ServerState) ->
+ case Service:process(Message, ServiceState) of
+ %% Normal reply
+ {reply, {ReplyCode, ReplyMessage}, NewServiceState} when is_integer(ReplyCode) ->
+ {ok, Encoded} = Service:encode(ReplyCode, ReplyMessage),
+ send_message(Encoded, ServerState),
+ NewServiceStates = dict:update(Service, NewServiceState, ServiceStates),
+ ServerState#state{states=NewServiceStates};
+ %% Streaming reply with reference
+ {reply, {stream, Ref}, NewServiceState} ->
+ NewServiceStates = dict:update(Service, NewServiceState, ServiceStates),
+ ServerState#state{states=NewServiceStates, req={Service,Ref}};
+ {error, Message, NewServiceState} ->
+ send_error(Message, ServerState),
+ NewServiceStates = dict:update(Service, NewServiceState, ServiceStates),
+ ServerState#state{states=NewServiceStates};
+ Other ->
+ send_error("Unknown service response: ~p", [Other], ServerState),
+ ServerState
+ end.
+
+
+%% @doc Sends a regular message to the client
+-spec send_message(binary(), #state{}) -> ok | {error, term()}.
+send_message(Bin, #state{socket=Sock}) ->
+ gen_tcp:send(Sock, Bin).
+
+%% @doc Sends an error message to the client
+-spec send_error(iolist(), #state{}) -> ok | {error, term()}.
+send_error(Message, State) ->
+ %% TODO: provide a service for encoding error messages? While
+ %% extra work, it would follow the pattern. On the other hand,
+ %% maybe it's too much abstraction. This is a hack, allowing us
+ %% to avoid including the header file.
+ Packet = riakc_pb:encode({rpberrorresp,Message,0}),
+ send_message(Packet, State).
+
+%% @doc Formats the terms with the given string and then sends an
+%% error message to the client.
+-spec send_error(io:format(), list(), #state{}) -> ok | {error, term()}.
+send_error(Format, Terms, State) ->
+ send_error(io_lib:format(Format, Terms), State).
97 src/riak_api_pb_service.erl
@@ -0,0 +1,97 @@
+%% -------------------------------------------------------------------
+%%
+%% riak_api_pb_service: Riak Client APIs Protocol Buffers Services
+%%
+%% Copyright (c) 2007-2010 Basho Technologies, Inc. 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.
+%%
+%% -------------------------------------------------------------------
+
+%% @doc 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:
+%% <pre>
+%% %% Register the 'ping' messages
+%% ok = riak_api_pb_service:register(riak_core_pb_service, 1, 2)
+%% </pre>
+%% @end
+
+-module(riak_api_pb_service).
+
+%% Behaviour API
+-export([behaviour_info/1]).
+
+%% Service-provider API
+-export([register/2,
+ register/3]).
+
+%% Server API
+-export([dispatch_table/0,
+ services/0]).
+
+%% @doc Behaviour information callback. PB API services must implement
+%% the given functions.
+behaviour_info(callbacks) ->
+ [{init,0},
+ {decode,2},
+ {encode,1},
+ {process,2}];
+behaviour_info(_) ->
+ undefined.
+
+%% @doc Registers a service module for a given message code.
+%% @equiv register(Module, Code, Code)
+%% @see register/3
+-spec register(Module::module(), Code::pos_integer()) -> ok | {error, Err::term()}.
+register(Module, Code) ->
+ register(Module, Code, Code).
+
+%% @doc 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.
+-spec register(Module::module(), MinCode::pos_integer(), MaxCode::pos_integer()) -> ok | {error, Err::term()}.
+register(_Module, MinCode, MaxCode) when MinCode > MaxCode ->
+ {error, invalid_message_code_range};
+register(Module, MinCode, MaxCode) ->
+ Registrations = dispatch_table(),
+ IsRegistered = fun(I) -> dict:is_key(I, Registrations) end,
+ CodeRange = lists:seq(MinCode, MaxCode),
+ case lists:filter(IsRegistered, CodeRange) of
+ [] ->
+ NewRegs = lists:foldl(fun(I, D) ->
+ dict:store(I, Module, D)
+ end, Registrations, CodeRange),
+ application:set_env(riak_api, services, NewRegs),
+ ok;
+ AlreadyClaimed ->
+ {error, {already_registered, AlreadyClaimed}}
+ end.
+
+%% @doc Returns the current mappings from message codes to service
+%% modules. This is called by riak_api_pb_socket on startup so that
+%% dispatches don't hit the application env.
+-spec dispatch_table() -> dict().
+dispatch_table() ->
+ app_helper:get_env(riak_api, services, dict:new()).
+
+%% @doc Returns the current registered PB services, based on the
+%% dispatch_table().
+-spec services() -> [ module() ].
+services() ->
+ lists:usort([ V || {_K,V} <- dict:to_list(dispatch_table()) ]).
55 src/riak_api_pb_sup.erl
@@ -0,0 +1,55 @@
+%% -------------------------------------------------------------------
+%%
+%% riak_api_pb_sup: supervise riak_api_pb_server processes
+%%
+%% Copyright (c) 2007-2010 Basho Technologies, Inc. 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.
+%%
+%% -------------------------------------------------------------------
+
+%% @doc supervise riak_api_pb_server processes
+
+-module(riak_api_pb_sup).
+-behaviour(supervisor).
+-export([start_link/0, init/1, stop/1]).
+-export([start_socket/0]).
+
+%% @doc Starts a PB socket server.
+-spec start_socket() -> {ok, pid()} | {error, term()}.
+start_socket() ->
+ supervisor:start_child(?MODULE, []).
+
+%% @doc Starts the PB server supervisor.
+-spec start_link() -> {ok, pid()} | {error, term()}.
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%% @doc Stops the PB server supervisor.
+-spec stop(term()) -> ok.
+stop(_S) -> ok.
+
+%% @doc The init/1 supervisor callback, initializes the supervisor.
+-spec init(list()) -> {ok,{{RestartStrategy,MaxR,MaxT},[ChildSpec]}} | ignore when
+ RestartStrategy :: supervisor:strategy(),
+ MaxR :: pos_integer(),
+ MaxT :: pos_integer(),
+ ChildSpec :: supervisor:child_spec().
+init([]) ->
+ {ok,
+ {{simple_one_for_one, 10, 10},
+ [{undefined,
+ {riak_api_pb_server, start_link, []},
+ temporary, brutal_kill, worker, [riak_api_pb_server]}]}}.
50 src/riak_api_sup.erl
@@ -0,0 +1,50 @@
+%% -------------------------------------------------------------------
+%%
+%% riak_api_sup: supervise the Riak API services
+%%
+%% Copyright (c) 2007-2010 Basho Technologies, Inc. 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.
+%%
+%% -------------------------------------------------------------------
+
+%% @doc supervise the Riak API services
+
+-module(riak_api_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/0,
+ init/1]).
+
+-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
+
+%% @doc Starts the supervisor.
+-spec start_link() -> {ok, pid()} | {error, term()}.
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%% @doc The init/1 supervisor callback, initializes the supervisor.
+-spec init(list()) -> {ok,{{RestartStrategy,MaxR,MaxT},[ChildSpec]}} | ignore when
+ RestartStrategy :: supervisor:strategy(),
+ MaxR :: pos_integer(),
+ MaxT :: pos_integer(),
+ ChildSpec :: supervisor:child_spec().
+init([]) ->
+ Processes = [
+ ?CHILD(riak_api_pb_sup, supervisor),
+ ?CHILD(riak_api_pb_listener, worker)
+ ],
+ {ok, {{one_for_one, 10, 10}, Processes}}.
Please sign in to comment.
Something went wrong with that request. Please try again.