# `Finitomata.Pool`
[🔗](https://github.com/am-kantox/finitomata/blob/v0.35.0/lib/finitomata/pool.ex#L1)

The instance of _FSM_ backed up by `Finitomata`.

- _entry event_ → `:__start__`
- _forks_ → `✗`
- _persistency_ → `✗`
- _listener_ → `✗`
- _timer_ → `✗`
- _hibernate_ → `✗`
- _cache_state_ → `✓`

## FSM representation

```mermaid
graph TD
    
    idle --> |init| ready
    idle --> |do| ready
    ready --> |do| ready
    ready --> |stop| done
    
```

### FSM paths

```elixir
↝‹:* ⇥ "__start__" ↦ :idle ⇥ "init" ↦ :ready ⇥ "stop" ↦ :done ⇥ "__end__" ↦ :*›
↝‹:* ⇥ "__start__" ↦ :idle ⇥ "do" ↦ :ready ⇥ "stop" ↦ :done ⇥ "__end__" ↦ :*›
```

### FSM loops

```elixir
↺‹:ready ⇥ "do" ↦ :ready›
```

---
Fully asynchronous pool to manage many similar processes, like connections.

The pool is to be started using `start_pool/1` directly or with `pool_spec/1` in the
  supervision tree.

`initialize/2` is explicitly separated because usually this is to be done after some
  external service initialization. In a case of `AMQP` connection management, one
  would probably start the connection process and then a pool to manage channels.

Once `initialize/2` has been called, the `run/3` function might be invoked to
  asynchronously execute the function passed as `actor` to `start_pool/1`.

If the callbacks `on_result/2` and/or `on_error/2` are defined, they will be invoked
  respectively. Finally, the message to the calling process will be sent, unless
  the third argument in a call to `run/3` is `nil`.

# `actor`
*since 0.18.0* 

```elixir
@type actor() :: naive_actor() | responsive_actor()
```

The actor function in the pool

# `handler`
*since 0.18.0* 

```elixir
@type handler() :: naive_handler() | responsive_handler()
```

The handler function in the pool

# `id`
*since 0.18.0* 

```elixir
@type id() :: Finitomata.id()
```

The ID of the Pool

# `naive_actor`
*since 0.18.0* 

```elixir
@type naive_actor() :: (term() -&gt; {:ok, term()} | {:error, any()})
```

The simple actor function in the pool

# `naive_handler`
*since 0.18.0* 

```elixir
@type naive_handler() :: (term() -&gt; any())
```

The simple handler of result/error in the pool

# `responsive_actor`
*since 0.18.0* 

```elixir
@type responsive_actor() :: (term(), Finitomata.State.payload() -&gt;
                         {:ok, term()} | {:error, any()})
```

The actor function in the pool, receiving the state as a second argument

# `responsive_handler`
*since 0.18.0* 

```elixir
@type responsive_handler() :: (term(), id() -&gt; any())
```

The actor function in the pool, receiving the state as a second argument

# `state`
*since 0.18.0* 

```elixir
@type state() :: :done | :ready | :idle | :*
```

Kind of event which might be send to initiate the transition.

## FSM representation

```mermaid
graph TD
    
    idle --> |init| ready
    idle --> |do| ready
    ready --> |do| ready
    ready --> |stop| done
    
```

# `t`
*since 0.18.0* 

```elixir
@type t() :: %Finitomata.Pool{
  on_result: any(),
  on_error: any(),
  actor: any(),
  payload: any(),
  errors: list(),
  id: any()
}
```

# `__config__`
*since 0.18.0* 

```elixir
@spec __config__(atom()) :: any()
```

Getter for the internal compiled-in _FSM_ information.

# `__generator__`
*since 0.18.0* 

See `Finitomata.Pool.__generator__/2`

# `__generator__`
*since 0.18.0* 

Returns the generator to be used in `StreamData`-powered property testing, based
  on the specification given to `use Estructura.Nested`, which contained

## shape
```elixir
%{
  id: {StreamData, :atom, [:alias]},
  errors: [:term],
  payload: :term,
  actor: {StreamData, :constant, [&Function.identity/1]},
  on_error: {Finitomata.Pool.Actor, :handler, [:error]},
  on_result: {Finitomata.Pool.Actor, :handler, [[]]}
}
```

The argument given would be used as a template to generate new values.

# `cast`
*since 0.18.0* 

Casts the map representation as given to `Estructura.Nested.shape/1` to
  the nested `Estructura` instance.

If `split: true` is passed as an option, it will attempt to put `foo_bar` into nested `%{foo: %{bar: _}}`

# `cast!`
*since 0.18.0* 

Same as `cast/2` but raises on errors.

# `child_spec`
*since 0.18.0* 

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `config`
*since 0.18.0* *macro* 

The convenient macro to allow using states in guards, returns a compile-time
  list of states for `Finitomata.Pool`.

# `get`
*since 0.18.0* 

```elixir
@spec get(
  %Finitomata.Pool{
    actor: term(),
    errors: term(),
    id: term(),
    on_error: term(),
    on_result: term(),
    payload: term()
  },
  Estructura.Config.key(),
  any()
) :: any()
```

Gets the value for the given key from the structure

# `initialize`
*since 0.18.0* 

```elixir
@spec initialize(Finitomata.id(), (pos_integer() -&gt; any()) | any()) :: :ok
```

Initializes the started _FSM_s with the same payload, or with what `payload_fun/1`
  would return as many times as the number of workers.

# `parse`
*since 0.18.0* 

```elixir
@spec parse(binary()) :: {:ok, struct()} | {:error, Exception.t()}
```

Safely parses the json, applying all the specified validations and coercions

# `parse!`
*since 0.18.0* 

```elixir
@spec parse!(binary()) :: struct() | no_return()
```

Same as `parse/1` but either returns the result of successful parsing or raises

# `pool_spec`
*since 0.18.0* 

```elixir
@spec pool_spec(keyword()) :: Supervisor.child_spec()
```

Child spec for `Finitomata.Pool` to embed the process into a supervision tree

# `put`
*since 0.18.0* 

```elixir
@spec put(
  %Finitomata.Pool{
    actor: term(),
    errors: term(),
    id: term(),
    on_error: term(),
    on_result: term(),
    payload: term()
  },
  Estructura.Config.key(),
  any()
) ::
  {:ok,
   %Finitomata.Pool{
     actor: term(),
     errors: term(),
     id: term(),
     on_error: term(),
     on_result: term(),
     payload: term()
   }}
  | {:error, any()}
```

Puts the value for the given key into the structure, passing coercion _and_ validation,
  returns `{:ok, updated_struct}` or `{:error, reason}` if there is no such key

# `put!`
*since 0.18.0* 

```elixir
@spec put!(
  %Finitomata.Pool{
    actor: term(),
    errors: term(),
    id: term(),
    on_error: term(),
    on_result: term(),
    payload: term()
  },
  Estructura.Config.key(),
  any()
) ::
  %Finitomata.Pool{
    actor: term(),
    errors: term(),
    id: term(),
    on_error: term(),
    on_result: term(),
    payload: term()
  }
  | no_return()
```

Puts the value for the given key into the structure, passing coercion _and_ validation,
  returns the value or raises if there is no such key

# `recalculate_calculated`
*since 0.18.0* 

Recalculates calculated fields for the instance of Finitomata.Pool.

Normally one would not need to call this function explicitly because `Access`
  implementation would do that.

# `run`
*since 0.18.0* 

```elixir
@spec run(Finitomata.id(), Finitomata.event_payload(), pid()) :: :ok
```

The runner for the `actor` function with the specified payload.

Basically, upon calling `run/3`, the following chain of calls would have happened:

1. `actor.(payload, state)` (or `actor.(payload)` if the function of arity one had been given)
2. `on_result(result, id)` / `on_error(result, id)` if callbacks are specified
3. the message of the shape `{:transition, :success/:failure, self(), {payload, result, on_result/on_error}})` 
   will be sent to `pid` unless `nil` given as a third argument 

# `start_link`
*since 0.18.0* 

Starts an _FSM_ alone with `name` and `payload` given.

Usually one does not want to call this directly, the most common way would be
to start a `Finitomata` supervision tree or even better embed it into
the existing supervision tree _and_ start _FSM_ with `Finitomata.start_fsm/4`
passing `Finitomata.Pool` as the first parameter.

For distributed applications, use `Infinitomata.start_fsm/4` instead.

# `start_pool`
*since 0.18.0* 

```elixir
@spec start_pool(
  id: Finitomata.id(),
  payload: :term,
  count: pos_integer(),
  actor: actor(),
  on_error: handler(),
  on_result: handler()
) :: GenServer.on_start()
```

Starts a pool of asynchronous workers wrapped by an _FSM_.

# `start_pool`
*since 0.18.0* 

```elixir
@spec start_pool(
  id :: Finitomata.id(),
  count :: pos_integer(),
  [actor: actor(), on_error: handler(), on_result: handler(), payload: :term]
  | %{
      :actor =&gt; actor(),
      optional(:on_error) =&gt; handler(),
      optional(:on_result) =&gt; handler(),
      optional(:payload) =&gt; :term
    }
  | [implementation: module(), payload: :term]
  | %{:implementation =&gt; module(), optional(:payload) =&gt; :term}
) :: GenServer.on_start()
```

# `validate`
*since 0.18.0* 

```elixir
@spec validate(t()) :: {:ok, t()} | {:error, keyword()}
```

Validates the instance of `Finitomata.Pool` with all the defined validators.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
