# `Kombu.Transport.Redis.QoS`
[🔗](https://github.com/hacktobeer/kombu/blob/v0.1.0/lib/kombu/transport/redis/qos.ex#L1)

Redis Ack Emulation (`kombu.transport.redis.QoS`).

Tracks unacknowledged messages in Redis using:
- a Hash (`unacked`) mapping `delivery_tag -> JSON([raw_msg, exchange, routing_key])`
- a Sorted Set (`unacked_index`) mapping `delivery_tag -> unix_timestamp`
- a Mutex key (`unacked_mutex`) for periodic restoration of messages exceeding `visibility_timeout`

# `restore_fun`

```elixir
@type restore_fun() :: (map(), String.t(), String.t(), boolean() -&gt; any())
```

# `t`

```elixir
@type t() :: %Kombu.Transport.Redis.QoS{
  client: Kombu.Transport.Redis.PrefixedClient.t() | nil,
  last_restored: number() | nil,
  restore_at_shutdown: boolean(),
  unacked_index_key: String.t(),
  unacked_key: String.t(),
  unacked_mutex_expire: pos_integer(),
  unacked_mutex_key: String.t(),
  virtual_qos: Kombu.Transport.Virtual.QoS.t(),
  visibility_timeout: pos_integer()
}
```

# `ack`

```elixir
@spec ack(t(), String.t()) :: t()
```

Acknowledges `delivery_tag`, removing it from Redis `unacked` / `unacked_index` and local QoS.

# `append`

```elixir
@spec append(t(), Kombu.Message.t(), String.t()) :: t()
```

Appends a delivered message to the Redis `unacked` hash and `unacked_index` sorted set,
as well as local channel QoS state.

# `can_consume?`

```elixir
@spec can_consume?(t()) :: boolean()
```

# `can_consume_max_estimate`

```elixir
@spec can_consume_max_estimate(t()) :: non_neg_integer() | nil
```

# `new`

```elixir
@spec new(Kombu.Transport.Redis.PrefixedClient.t(), keyword()) :: t()
```

# `reject`

```elixir
@spec reject(t(), String.t(), keyword()) :: t()
```

Rejects `delivery_tag`. If `requeue: true`, restores the message to the front of its queue (`leftmost: true`).

# `remove_from_table`

```elixir
@spec remove_from_table(t(), String.t()) :: [term()]
```

Removes `delivery_tag` from `unacked_index` and `unacked` in Redis.

# `restore_by_tag`

```elixir
@spec restore_by_tag(t(), String.t(), restore_fun(), keyword()) :: :ok
```

Looks up `delivery_tag` in `unacked`, deletes it from `unacked` and `unacked_index`,
and invokes `restore_fun.(raw_message, exchange, routing_key, leftmost)` if found.

# `restore_unacked`

```elixir
@spec restore_unacked(t(), restore_fun()) :: t()
```

Restores all unacknowledged messages tracked by this channel instance.

# `restore_unacked_once`

```elixir
@spec restore_unacked_once(t(), restore_fun()) :: t()
```

Restores unacked messages once during channel shutdown if `restore_at_shutdown` is enabled.

# `restore_visible`

```elixir
@spec restore_visible(t(), restore_fun(), keyword()) ::
  {:ok, non_neg_integer(), t()} | {:throttled, t()} | {:locked, t()}
```

Scans `unacked_index` for messages older than `visibility_timeout` and restores them,
holding a distributed Redis mutex (`unacked_mutex`) during restoration.

# `set_prefetch_count`

```elixir
@spec set_prefetch_count(t(), non_neg_integer()) :: t()
```

---

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