Module sregulator

This module provides a job regulator for controlling the level of concurrency of processes carrying out a task.

This module defines the sregulator behaviour.
Required callback functions: init/1.

Description

This module provides a job regulator for controlling the level of concurrency of processes carrying out a task. A process requests permission to run and is queued until it is allowed to begin. Once the task is complete the process informs the regulator that is is done. Alternatively the process can ask if it can continue running and gains priority over any queued processes. The queue is managed using an sbroker_queue callback module, and the level of concurrency by an sregulator_valve callback module. The message queue delay and processing delay are monitorred by an sbroker_meter.

The main function to ask to begin is ask/1, which blocks until the request is accepted or the queue drops the request. done/3 is then called after the task has finished or continue/2 to continue.

A regulator requires a callback module to be configured, in a similar way to a supervisor's children are specified. The callback modules implements one callback, init/1, with single argument Args. init/1 should return {ok, {QueueSpec, ValveSpec, [MeterSpec]}} or ignore. QueueSpec is the sbroker_queue specification, ValveSpec is the sregulator_valve specification and MeterSpec is a sbroker_meter specification. There can be any number of meters but a meter module can only be included once. All three take the same format: {Module, Args}, where Module is the callback module and Args the arguments term for the module. In the case of ignore the regulator is not started and start_link returns ignore. As the callback modules are defined in the init/1 callback a regulator supports the dynamic modules supervisor child specification.

For example:

  -module(sregulator_example).
 
  -behaviour(sregulator).
 
  -export([start_link/0]).
  -export([ask/0]).
  -export([continue/1]).
  -export([done/1]).
  -export([init/1]).
 
  start_link() ->
      sregulator:start_link({local, ?MODULE}, ?MODULE, [], []).
 
  ask() ->
      case sregulator:ask(?MODULE) of
          {go, Ref, _, _, _} -> {ok, Ref};
          {drop, _}          -> {error, dropped}
      end.
 
  continue(Ref) ->
      case sregulator:continue(?MODULE, Ref, 5000) of
         {go, Ref, _, _, _} -> {ok, Ref};
         {done, _}          -> {error, dropped};
         {not_found, _}     -> {error, not_found}
      end.
 
  done(Ref
 
  init([]) ->
    QueueSpec = {sbroker_codel_queue, {out, 50, 500, drop_r, 64}},
    ValveSpec = {sregulator_open_valve, 30},
    MeterSpec = {sbroker_overload_meter, {50, 500, {?MODULE, overload}}},
    {ok, {QueueSpec, ValveSpec, [MeterSpec]}}.

Data Types

debug_option()

debug_option() = trace | log | {log, pos_integer()} | statistics | {log_to_file, file:filename()} | {install, {function(), any()}}

handler_spec()

handler_spec() = {module(), any()}

name()

name() = {local, atom()} | {global, any()} | {via, module(), any()}

regulator()

regulator() = pid() | atom() | {atom(), node()} | {global, any()} | {via, module(), any()}

start_option()

start_option() = {debug, debug_option()} | {timeout, timeout()} | {spawn_opt, [proc_lib:spawn_option()]} | {read_time_after, non_neg_integer() | infinity}

start_return()

start_return() = {ok, pid()} | ignore | {error, any()}

Function Index

ask/1Send a run request to the regulator, Regulator.
async_ask/1Monitor the regulator and send an asynchronous run request.
async_ask/2Send an asynchronous run request using tag, Tag.
await/2Await the response to an asynchronous request idenitifed by Tag.
cancel/3Cancel an asynchronous request.
cast/2Update the valve in the regulator without waiting for the regulator to handle the update.
change_config/2Change the configuration of the regulator.
continue/2Send a request to continue running using an existing lock reference, Ref.
done/3Inform the regulator the process has finished running and release the lock, Ref.
dynamic_ask/1Send a run request to the regulator, Regulator.
len/2Get the length of the internal queue in the regulator, Regulator.
nb_ask/1Send a run request to the regulator, Regulator, but do not enqueue the request if not immediately allowed to run.
size/2Get the number of processes holding a lock with the regulator, Regulator.
start_link/3Starts a regulator with callback module Module and argument Args, and regulator options Opts.
start_link/4Starts a regulator with name Name, callback module Module and argument Args, and regulator options Opts.
update/3Synchronously update the valve in the regulator.

Function Details

ask/1

ask(Regulator) -> Go | Drop

Send a run request to the regulator, Regulator.

Returns {go, Ref, RegulatorPid, RelativeTIme, SojournTime} on successfully being allowed to run or {drop, SojournTime}.

Ref is the lock reference, which is a reference(). RegulatorPid is the pid() of the regulator process. RelativeTime is the time difference between when the request was sent and the message that opened the regulator's valve was sent. SojournTime is the approximate time spent in both the regulator's message queue and internal queue.

RelativeTime represents the SojournTime without the overhead of the regulator. The value measures the queue congestion without being effected by the load of the regulator or node.

If RelativeTime is positive, the request was enqueued in the internal queue awaiting a message to open the value that was sent approximately RelativeTime ater this request was sent. Therefore SojournTime minus RelativeTime is the latency, or overhead, of the regulator.

If RelativeTime is negative, the regulator's valve was opened by a message sent abs(RelativeTime) before this request. Therefore SojournTime is the latency, or overhead, of the regulator.

If RelativeTime is 0, the request was sent at approximately the same as the message that open the regulator's valve.

async_ask/1

async_ask(Regulator) -> {await, Tag, Process} | {drop, 0}

Monitor the regulator and send an asynchronous run request. Returns {await, Tag, Process}.

Tag is a monitor reference() that uniquely identifies the reply containing the result of the request. Process is the pid() of the regulator or {atom(), node()} if the regulator is registered locally on a different node.

The reply is of the form {Tag, Msg} where Msg is either {go, Ref, RegulatorPid, RelativeTime, SojournTime} or {drop, SojournTime}.

Ref is the lock reference, which is a reference(). RegulatorPid is the pid() of the regulator process. RelativeTime is the time difference between when the request was sent and the message that opened the regulator's valve was sent. SojournTime is the approximate time spent in both the regulator's message queue and internal queue.

Multiple asynchronous requests can be made from a single process to a regulator and no guarantee is made of the order of replies. A process making multiple requests can reuse the monitor reference for subsequent requests to the same regulator process (Process) using async_ask/2.

If the request is dropped when using via module sprotector returns {drop, 0} and does not send the request.

See also: async_ask/2, cancel/2.

async_ask/2

async_ask(Regulator, To) -> {await, Tag, Process} | {drop, 0}

Send an asynchronous run request using tag, Tag. Returns {await, Tag, Process}.

To is a tuple containing the process, pid(), to send the reply to and Tag, any(), that idenitifes the reply containing the result of the request. Process is the pid() of the regulator or {atom(), node()} if the regulator is registered locally on a different node.

Otherwise this function is equivalent to async_ask/1.

See also: async_ask/1, cancel/2.

await/2

await(Tag, Timeout) -> Go | Drop

Await the response to an asynchronous request idenitifed by Tag.

Exits if a response is not received after Timeout milliseconds.

Exits if a DOWN message is received with reference Tag.

See also: async_ask/1, async_ask/2.

cancel/3

cancel(Regulator, Tag, Timeout) -> Count | false

Cancel an asynchronous request.

Returns the number of cancelled requests or false if no requests exist with tag Tag. In the later case a caller may wish to check is message queue for an existing reply.

See also: async_ask/1, async_ask/2.

cast/2

cast(Regulator, Value) -> ok

Update the valve in the regulator without waiting for the regulator to handle the update.

Value is an integer().

Returns ok.

change_config/2

change_config(Regulator, Timeout) -> ok | {error, Reason}

Change the configuration of the regulator. Returns ok on success and {error, Reason} on failure, where Reason is the reason for failure.

The regulators calls the init/1 callback to get the new configuration. If init/1 returns ignore the config does not change.

continue/2

continue(Regulator, Ref) -> Go | Stop | NotFound | Drop

Send a request to continue running using an existing lock reference, Ref. The request is not queued.

Returns {go, Ref, RegulatorPid, RelativeTime, SojournTime} on successfully being allowed to run, {stop, SojournTime} when the process should stop running or {not_found, SojournTime} when the lock reference does not exist on the regulator.

Ref is the lock reference, which is a reference(). RegulatorPid is the pid() of the regulator process. RelativeTime is the time difference between when the request was sent and the message that opened the regulator's valve was sent. SojournTime is the approximate time spent in the regulator's message queue.

If the request is dropped when using via module sprotector returns {drop, 0} and does not send the request. In this situation the Ref is still a valid lock on the regulator.

See also: ask/1.

done/3

done(Regulator, Ref, Timeout) -> Stop | NotFound

Inform the regulator the process has finished running and release the lock, Ref.

Returns {stop, SojournTime} if the regulator acknowledged the process has stopped running or {not_found, SojournTime} if the lock reference, Ref, does not exist on the regulator.

SojournTime is the time the request spent in the regulator's message queue.

See also: ask/1.

dynamic_ask/1

dynamic_ask(Regulator) -> Go | Await | Drop

Send a run request to the regulator, Regulator. If not immediately allowed to run the request is converted to an async_ask/1.

Returns {go, Ref, RegulatorPid, RelativeTime, SojournTime} on successfully being allowed to run or {await, Tag, RegulatorPid}.

Ref is the lock reference, which is a reference(). RegulatorPid is the pid() of the regulator process. RelativeTime is the time difference between when the request was sent and the message that opened the regulator's valve was sent. SojournTime is the approximate time spent in the regulator's message queue. Tag is a monitor reference, as returned by async_ask/1.

If the request is dropped when using via module sprotector returns {drop, 0} and does not send the request.

See also: async_ask/1, nb_ask/1.

len/2

len(Regulator, Timeout) -> Length

Get the length of the internal queue in the regulator, Regulator.

nb_ask/1

nb_ask(Regulator) -> Go | Drop

Send a run request to the regulator, Regulator, but do not enqueue the request if not immediately allowed to run.

Returns {go, Ref, RegulatorPid, RelativeTime, SojournTime} on successfully being allowed to run or {drop, SojournTime}.

Ref is the lock reference, which is a reference(). RegulatorPid is the pid() of the regulator process. RelativeTime is the time difference between when the request was sent and the message that opened the regulator's valve was sent. SojournTime is the approximate time spent in the regulator's message queue.

If the request is dropped when using via module sprotector returns {drop, 0} and does not send the request.

See also: ask/1.

size/2

size(Regulator, Timeout) -> Size

Get the number of processes holding a lock with the regulator, Regulator.

start_link/3

start_link(Module, Args, Opts) -> StartReturn

Starts a regulator with callback module Module and argument Args, and regulator options Opts.

Opts is a proplist and supports debug, timeout and spawn_opt used by gen_server and gen_fsm. read_time_after sets the number of requests when a cached time is stale and the time is read again. Its value is non_neg_integer() or infinity and defaults to 16.

See also: gen_server:start_link/3.

start_link/4

start_link(Name, Module, Args, Opts) -> StartReturn

Starts a regulator with name Name, callback module Module and argument Args, and regulator options Opts.

See also: start_link/3.

update/3

update(Regulator, Value, Timeout) -> ok

Synchronously update the valve in the regulator.

Value is an integer() and Timeout is the timout, timeout(), to wait in milliseconds for the regulator to reply to the update.

Returns ok.


Generated by EDoc, Sep 29 2016, 17:17:28.