# `Jido.Chat.Concurrency`
[🔗](https://github.com/agentjido/jido_chat/blob/v1.2.0/lib/jido/chat/concurrency.ex#L1)

Chat-level overlapping-message concurrency configuration.

The model is a pure state protocol. It does not start timers or processes.
Callers supply `now_ms` when they need deterministic timing and call
`Jido.Chat.drain_lock/4` after the configured idle window.

Queue and burst entries default to a size of 10 and a lifetime of 90 seconds.
Burst and debounce idle windows default to 1.5 seconds. Concurrent handlers
are unbounded unless `max_concurrent` is set.

# `lock_scope`

```elixir
@type lock_scope() :: :thread | :channel
```

# `overflow_policy`

```elixir
@type overflow_policy() :: :drop_oldest | :drop_newest
```

# `pending_entry`

```elixir
@type pending_entry() :: %{
  owner: String.t(),
  strategy: strategy(),
  metadata: map(),
  enqueued_at: non_neg_integer(),
  expires_at: pos_integer(),
  ready_at: non_neg_integer(),
  conversation_key: String.t()
}
```

# `strategy`

```elixir
@type strategy() :: :reject | :queue | :debounce | :burst | :concurrent
```

# `t`

```elixir
@type t() :: %Jido.Chat.Concurrency{
  debounce_ms: integer(),
  lock_scope: :thread | :channel,
  max_concurrent: nil | nil | integer(),
  max_queue_size: integer(),
  metadata: map(),
  overflow_policy: :drop_oldest | :drop_newest,
  queue_entry_ttl_ms: integer(),
  strategy: :reject | :queue | :debounce | :burst | :concurrent
}
```

# `lock_key`

```elixir
@spec lock_key(t() | map() | keyword(), String.t(), String.t() | nil) :: String.t()
```

Returns the lock key for the configured thread or channel scope.

# `message_context`

```elixir
@spec message_context([map()]) :: Jido.Chat.MessageContext.t()
```

Returns a deterministic message context for drained pending entries.

# `new`

```elixir
@spec new(t() | map() | keyword()) :: t()
```

Creates a normalized concurrency config.

# `schema`

Returns the schema for concurrency configuration.

---

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