# `NoNoncense.MachineId.Strategy`
[🔗](https://github.com/juulSme/NoNoncense/blob/v2.0.0/lib/no_noncense/machine_id/strategy.ex#L1)

Behaviour for pluggable machine ID lease strategies, used by `NoNoncense.MachineId.LeaseManager`
to coordinate unique machine ID assignment across nodes (e.g. through SQL or Redis).

A strategy must hand back the same `machine_id` to a given node/identity across `acquire/2` and
successive `renew/3` calls - callers rely on this to keep using the same ID for the lifetime of a lease.

`lease_duration` is the duration (in ms) the caller would like the lease to be valid for; a
strategy may grant a different duration (e.g. clamped to its own bounds) via the returned `ttl_ms`.

Strategies must grant leases of at least 30 seconds. `LeaseManager` uses the returned `ttl_ms`
to schedule both renewal and a local expiry deadline, with safety margins before the actual
expiry. A shorter lease is treated as lost and its factories are disabled.

`renew/3` distinguishes two failure modes so callers can tell confirmed loss from mere uncertainty:

  * `{:error, :lost, reason}` - the strategy positively confirms the lease is no longer held
    (e.g. another node holds it now, or the coordinator explicitly rejects the renewal).
  * `{:error, :retry, reason}` - an ambiguous/transient failure (timeout, connection error); the
    strategy cannot confirm whether the lease is still valid.

# `acquire`

```elixir
@callback acquire(lease_duration :: pos_integer(), strategy_opts :: keyword()) ::
  {:ok, machine_id :: 0..511, lease :: term(), ttl_ms :: pos_integer()}
  | {:error, reason :: term()}
```

Acquire a new lease, returning the assigned machine ID and its actual validity period.

# `deterministic?`

```elixir
@callback deterministic?() :: boolean()
```

Indicates if the strategy will always return the same ID; re-acquisition is pointless if a conflict is detected.

Dynamic strategies (SqlLease and RedisLease for example) should override this and return false to enable re-acquisition attempts by the lease manager.

# `release`

```elixir
@callback release(lease :: term(), strategy_opts :: keyword()) :: :ok
```

Best-effort release of a lease, e.g. on graceful shutdown.

# `renew`

```elixir
@callback renew(
  lease :: term(),
  lease_duration :: pos_integer(),
  strategy_opts :: keyword()
) ::
  {:ok, lease :: term(), ttl_ms :: pos_integer()}
  | {:error, :lost, reason :: term()}
  | {:error, :retry, reason :: term()}
```

Renew an existing lease, extending its validity period.

# `__using__`
*macro* 

Imports the strategy behaviour and default stateless `renew/3` and `release/2` callbacks.

---

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