lifeguard
Types
An error returned when failing to use a pooled worker.
pub type ApplyError {
NoResourcesAvailable
}
Constructors
-
NoResourcesAvailable
The strategy used to check out a resource from the pool.
pub type CheckoutStrategy {
FIFO
LIFO
}
Constructors
-
FIFOCheck out workers with a first-in-first-out strategy. Operates like a queue.
-
LIFOCheck out workers with a last-in-first-out strategy. Operates like a stack.
A type returned by a worker’s initialisation function. It contains the worker’s initial state, along with an optional selector that can be used to send messages to the worker.
If provided, the selector will be used instead of the default, which just selects
from the worker’s own subject. You can provide a custom selector using the
selecting function.
pub opaque type Initialised(state, msg)
Values
pub fn broadcast(
pool pool: process.Subject(PoolMsg(msg)),
msg msg: msg,
) -> Nil
Send a message to all pooled actors, regardless of checkout status.
Panics
Like gleam/erlang/process.send,
this will panic if the pool is not running.
pub fn call(
pool pool: process.Subject(PoolMsg(msg)),
msg msg: fn(process.Subject(return_type)) -> msg,
checkout_timeout checkout_timeout: Int,
call_timeout call_timeout: Int,
) -> Result(return_type, ApplyError)
Send a message to a pooled actor and wait for a response. Equivalent to process.call
using a pooled worker.
Panics
Like gleam/erlang/process.call,
this will panic if the pool is not running, or if the worker crashes while
handling the message.
pub fn checkout_strategy(
builder builder: Builder(state, msg),
strategy checkout_strategy: CheckoutStrategy,
) -> Builder(state, msg)
Set the order in which actors are checked out from the pool. Defaults to FIFO.
pub fn initialised(state: state) -> Initialised(state, msg)
Create a new Initialised value with the given state and no selector.
pub fn new(
name: process.Name(PoolMsg(msg)),
state: state,
) -> Builder(state, msg)
Create a new Builder for creating a pool of worker actors.
This API mimics the Actor API from gleam/otp/actor,
so it should be familiar to anyone already using OTP with Gleam.
You must provide a name for the pool. You can then send messages to the pool by creating a named subject with this name.
import lifeguard
pub fn main() {
let pool_name = process.new_name("pool")
// Create a pool of 10 actors that do nothing.
let assert Ok(pool) =
lifeguard.new(pool_name, initial_state)
|> lifeguard.on_message(fn(msg, state) { actor.continue(state) })
|> lifeguard.size(10)
|> lifeguard.start(1000)
}
Default values
| Config | Default |
|---|---|
on_message | fn(state, _) { actor.continue(state) } |
size | 10 |
checkout_strategy | FIFO |
pub fn new_with_initialiser(
name: process.Name(PoolMsg(msg)),
timeout: Int,
initialiser: fn(process.Subject(msg)) -> Result(
Initialised(state, msg),
String,
),
) -> Builder(state, msg)
Create a new Builder with a custom initialiser that runs before the
worker’s message loop starts.
You must provide a name for the pool. You can then send messages to the pool by creating a named subject with this name.
The second argument is the number of milliseconds the initialiser is expected to return within. The actor will be terminated if it does not complete within the specified time, and the creation of the pool will fail.
The initialiser is given the worker’s default subject, which can optionally be
used to create a custom selector for the worker to receive messages. See the
selecting function for more information.
This API mimics the Actor API from gleam/otp/actor,
so it should be familiar to anyone already using OTP with Gleam.
Default values
| Config | Default |
|---|---|
on_message | fn(state, _) { actor.continue(state) } |
size | 10 |
checkout_strategy | FIFO |
pub fn on_message(
builder builder: Builder(state, msg),
handler handler: fn(state, msg) -> actor.Next(state, msg),
) -> Builder(state, msg)
Set the message handler for actors in the pool. This operates exactly like
gleam/otp/actor.on_message.
pub fn pid(
pool pool: process.Subject(PoolMsg(msg)),
) -> Result(process.Pid, Nil)
Get the supervisor PID for a running pool.
Returns an error if the pool is not running.
pub fn selecting(
initialised: Initialised(state, msg),
selector: process.Selector(msg),
) -> Initialised(state, msg)
Provide a selector for your worker to receive messages with. If your worker receives a message that isn’t selected, the message will be discarded and a warning will be logged.
If you don’t provide a selector, the worker will receive messages from its own subject,
equivalent to process.select(process.new_selector(), process.new_subject()). If you
provide a selector, the default selector will be overwritten.
pub fn send(
pool pool: process.Subject(PoolMsg(msg)),
msg msg: msg,
checkout_timeout checkout_timeout: Int,
) -> Result(Nil, ApplyError)
Send a message to a pooled worker. Equivalent to process.send using a pooled actor.
Panics
Like gleam/erlang/process.send,
this will panic if the pool is not running.
pub fn shutdown(
pool pool: process.Subject(PoolMsg(msg)),
) -> Result(Nil, Nil)
Shut down a pool and all its workers. Fails if the pool is not currently running.
You only need to call this when using unsupervised pools. You should let your supervision tree handle the shutdown of supervised worker pools.
pub fn size(
builder builder: Builder(state, msg),
size size: Int,
) -> Builder(state, msg)
Set the number of actors in the pool. Defaults to 10.
pub fn start(
builder builder: Builder(state, msg),
timeout init_timeout: Int,
) -> Result(static_supervisor.Supervisor, actor.StartError)
Start an unsupervised pool using the given Builder. You can then send
messages to the pool by creating a named subject. In most cases, you should use the
supervised function instead.
Note: this function mimics the behaviour of supervisor:start_link and
gleam/otp/static_supervisor’s start_link function and will exit the process if
any of the workers fail to start.
pub fn supervised(
builder builder: Builder(state, msg),
timeout init_timeout: Int,
) -> supervision.ChildSpecification(static_supervisor.Supervisor)
Return the ChildSpecification
for creating a supervised worker pool.
Example
// Create a name for the pool. We can use this to send messages to the pool once it
// has been started.
let pool_name = process.new_name("db_connection_pool")
let assert Ok(_started) =
supervisor.new(supervisor.OneForOne)
|> supervisor.add(
lifeguard.new(pool_name, state)
|> lifeguard.supervised(1000)
)
|> supervisor.start
let pool = process.named_subject(pool_name)
let assert Ok(_) = lifeguard.send(pool, Message)