View Source Handler.Pool (handler v0.5.0)
Manage a pool of resources used to run dangerous functions
The Pool provides both a synchrous interface (run/3
) as well as an asynchronous
interface (async/3
and await/1
) for running functions.
composing-pools
Composing Pools
This module also provides a way to have limited resources for particular use-cases, that end up
sharing bigger pools of resources. Take for instance a hosted multi-tenant application where you
can safely use up to 10GB of memory for a particular task, but you don't want any one customer to
use the whole pool, so each customer has a limit of just 5GB. You can handle this scenario using
the delegate_to
configuration.
{:ok, _pid} = Handler.Pool.start_link(%Handler.Pool{
max_memory: 10 * 1024 * 1024 * 1024,
name: :shared_pool
})
{:ok, _pid} = Handler.Pool.start_link(%Handler.Pool{
delegate_to: :shared_pool,
max_memory: 5 * 1024 * 1024 * 1024,
name: :customer_pool
})
100 = Pool.run(:customer_pool, fn -> 10 * 10 end, max_heap_bytes: 100 * 1024)
Link to this section Summary
Functions
Asynchronously start a job
Wait for the result of a job kicked off by async
Returns a specification to start this module under a supervisor.
Kill all jobs in a pool. Returns the number of killed jobs.
Kill jobs by their :name
Kill a job by its ref
Run a potentially dangerous function in the pool
Link to this section Types
Specs
exception() :: Handler.Pool.InsufficientMemory.t() | Handler.Pool.NoWorkersAvailable.t() | Handler.Pool.Timeout.t()
Specs
name() :: GenServer.name()
Specs
opt() :: Handler.opt() | {:task_name, String.t()} | {:delegate_param, term()} | {:pool_timeout, Handler.milliseconds()}
Specs
opts() :: [opt()]
Specs
pool() :: GenServer.server()
Specs
t() :: %Handler.Pool{ delegate_fun: nil | {module(), fn_name :: atom(), first_argument :: term()}, delegate_to: nil | name(), max_memory_bytes: non_neg_integer(), max_workers: non_neg_integer(), name: nil | name() }
Link to this section Functions
Specs
Asynchronously start a job
Take a potentially dangerous function and run it in the pool. You'll either get back an ok tuple with
a reference you can pass to the await/1
function, or a reject tuple with an exception describing
why the function couldn't be started.
Specs
await(reference()) :: any() | {:error, Handler.exception()}
Wait for the result of a job kicked off by async
Returns a specification to start this module under a supervisor.
See Supervisor
.
flush(pool, exception \\ %{__exception__: true, __struct__: Handler.ProcessExit, message: "User killed the process", reason: :user_killed})
View SourceKill all jobs in a pool. Returns the number of killed jobs.
The client that kicked off the work will receive an {:error, exception}
as the result for the job. If you don't pass an exception, you will get back
a Handler.ProcessExit{reason: :user_killed}
by default.
kill(pool, task_name, exception \\ %{__exception__: true, __struct__: Handler.ProcessExit, message: "User killed the process", reason: :user_killed})
View SourceKill jobs by their :name
When kicking off a job the :name
option can be set and then later
this function can be used to kill any jobs in progress with a :name
matching the task_name
of this function.
The client that kicked off the work will receive an {:error, exception}
as the result for the job. If you don't pass an exception, you will get back
a Handler.ProcessExit{reason: :user_killed}
by default.
kill_by_ref(pool, ref, exception \\ %{__exception__: true, __struct__: Handler.ProcessExit, message: "User killed the process", reason: :user_killed})
View SourceKill a job by its ref
When kicking off a job with the async/3
function a ref
is returned
and that job can later be killed.
The client that kicked off the work will receive an {:error, exception}
as the result for the job. If you don't pass an exception, you will get back
a Handler.ProcessExit{reason: :user_killed}
by default.
Specs
run(pool(), (() -> any()), opts()) :: any() | {:error, Handler.exception()} | {:reject, exception()}
Run a potentially dangerous function in the pool
This function has pretty much the same interface as Handler.run/2
with
the addition of the {:reject, t:exception()}
return values when the pool
does not have enough resources to start a particular function.