# `ExGram.Dispatcher`
[🔗](https://github.com/rockneurotiko/ex_gram/blob/0.65.0/lib/ex_gram/dispatcher.ex#L1)

Named GenServer process that receives updates, applies middlewares for the bot,
and calls the bot's `c:ExGram.Handler.handle/2` callback.

This module is started automatically by the bot's supervisor and shouldn't be
interacted with directly in most cases.

## Handler Mode

The `handler_mode` option controls how the handler is executed after an update
arrives:

  * `:async` (default in production) - the handler is spawned in a separate process.
    The dispatcher returns immediately after receiving the update, and the handler
    runs concurrently.
  * `:sync` - the handler runs inline inside the dispatcher's `handle_call`. The
    caller blocks until the full pipeline (middlewares + handler + API calls) has
    completed. **`ExGram.Test.start_bot/3` defaults to `:sync`** so that
    `ExGram.Test.push_update/2` is fully synchronous in tests.

The `handler_mode` can be set as a bot startup option:

    # In production (default)
    MyApp.Bot.start_link(handler_mode: :async)

    # In tests via ExGram.Test.start_bot/3 (default)
    ExGram.Test.start_bot(context, MyApp.Bot)
    # equivalent to:
    ExGram.Test.start_bot(context, MyApp.Bot, handler_mode: :sync)

# `custom_key`

```elixir
@type custom_key() :: any()
```

# `init_opts`

```elixir
@type init_opts() :: [
  setup_commands: boolean(),
  handler_mode: :sync | :async | nil,
  get_me: boolean()
]
```

# `parsed_message`

```elixir
@type parsed_message() ::
  {:command, key :: String.t() | custom_key(), ExGram.Model.Message.t()}
  | {:text, String.t(), ExGram.Model.Message.t()}
  | {:regex, key :: custom_key(), ExGram.Model.Message.t()}
  | {:location, ExGram.Model.Location.t()}
  | {:message, ExGram.Model.Message.t()}
  | {:callback_query, ExGram.Model.CallbackQuery.t()}
  | {:inline_query, ExGram.Model.InlineQuery.t()}
  | {:edited_message, ExGram.Model.Message.t()}
  | {:pinned_message, ExGram.Model.Message.t()}
  | {:update, ExGram.Model.Update.t()}
```

# `t`

```elixir
@type t() :: %ExGram.Dispatcher{
  bot_info: ExGram.Model.User.t() | nil,
  bot_inits: [{module(), keyword()}],
  bot_module: module() | nil,
  commands: %{required(String.t()) =&gt; map()},
  dispatcher_name: atom(),
  error_handler: {module(), atom()},
  extra_info: map(),
  handler: {module(), atom()},
  handler_mode: :sync | :async,
  init_opts: init_opts(),
  middlewares: [ExGram.Bot.middleware()],
  name: atom(),
  regex: [Regex.t()]
}
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `init_state`

```elixir
@spec init_state(atom(), module(), init_opts(), map()) :: t()
```

# `new`

```elixir
@spec new(Enumerable.t()) :: t()
```

# `start_link`

```elixir
@spec start_link(t()) :: GenServer.on_start()
```

---

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