# `ASM.Extensions.Routing.HealthTracker`
[🔗](https://github.com/nshkrdotcom/agent_session_manager/blob/v0.9.2/lib/asm/extensions/routing/health_tracker.ex#L1)

Provider health state machine with temporary exclusion windows.

# `health_status`

```elixir
@type health_status() :: %{
  status: :healthy | :degraded | :unhealthy,
  failures: non_neg_integer(),
  last_error: term() | nil,
  excluded_until_ms: integer() | nil,
  excluded?: boolean()
}
```

Per-provider health status.

# `provider_id`

```elixir
@type provider_id() :: term()
```

Unique provider candidate identifier used by the router.

# `t`

```elixir
@type t() :: %ASM.Extensions.Routing.HealthTracker{
  by_provider: %{required(provider_id()) =&gt; tracker_state()},
  failure_cooldown_ms: pos_integer()
}
```

# `available_provider_ids`

```elixir
@spec available_provider_ids(t(), integer()) :: [provider_id()]
```

# `mark_failure`

```elixir
@spec mark_failure(t(), provider_id(), term(), integer()) ::
  {:ok, t()} | {:error, ASM.Error.t()}
```

# `mark_success`

```elixir
@spec mark_success(t(), provider_id(), integer()) ::
  {:ok, t()} | {:error, ASM.Error.t()}
```

# `new`

```elixir
@spec new(
  [provider_id()],
  keyword()
) :: {:ok, t()} | {:error, ASM.Error.t()}
```

# `refresh`

```elixir
@spec refresh(t(), integer()) :: t()
```

# `snapshot`

```elixir
@spec snapshot(t(), integer()) :: %{required(provider_id()) =&gt; health_status()}
```

# `status`

```elixir
@spec status(t(), provider_id(), integer()) ::
  {:ok, health_status()} | {:error, ASM.Error.t()}
```

---

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