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

Acquires and renews a machine ID lease through a pluggable `NoNoncense.MachineId.Strategy`,
directly managing the configured `NoNoncense` factories.

Initial acquisition blocks startup. Once leased, the manager renews before the earlier of the
configured renewal interval and the strategy-provided TTL. A confirmed loss or local expiry
disables every configured factory, invokes `:on_lease_lost` with a reason, and schedules
reacquisition. A successful reacquisition reinitializes the factories with the new machine ID.

An ambiguous renewal failure is retried while the known-valid window remains open. On graceful
shutdown, the manager makes a best-effort call to the strategy's `release/2` callback when it
still holds a lease.

## Options

  * `:name` - registered name (default `NoNoncense.MachineId.LeaseManager`)
  * `:strategy` (required) - a module implementing the `NoNoncense.MachineId.Strategy` behaviour
  * `:strategy_opts` - passed as-is to the strategy's callbacks (default `[]`)
  * `:lease_duration` - the duration, in ms, to request from the strategy on every
    `acquire`/`renew` call (the strategy may grant a different actual duration; default 8 hours)
  * `:renew_interval` - how often to renew, in ms; should be comfortably shorter than the
    lease's actual TTL to allow for retries (default 30 minutes)
  * `:acquire_timeout` - max total time, in ms, to keep retrying acquisition at boot before giving up
    and failing `start_link/1` (default `60_000`; pass `:infinity` to retry forever)
  * `:on_lease_lost` - called with the reason for the lease loss. Can be used to halt the entire node, for example. Note that on lease loss, all NoNoncense factories are always disabled to preserve uniqueness guarantees.

### Lease duration and renew interval

The defaults leave a wide recovery window for a temporary connection loss to your coordinator
(e.g. your database), while still renewing well ahead of the lease's expiration. If you
override these, keep that balance intact - most practical uses of nonce generation, such as
ID generation, will grind to a halt if generation stops, so favor conservative, generous
durations over aggressive, short ones. Machine IDs are meant to stay static for the lifetime
of the node, so there's little to be gained from renewing more aggressively.

# `opt`

```elixir
@type opt() ::
  {:name, GenServer.name()}
  | {:strategy, module()}
  | {:strategy_opts, keyword()}
  | {:lease_duration, pos_integer()}
  | {:renew_interval, pos_integer()}
  | {:acquire_timeout, pos_integer() | :infinity}
  | {:on_lease_lost, (term() -&gt; any())}
  | {:instances, [NoNoncense.init_opt()]}
  | {:lease_cache, GenServer.name()}
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `lease_lost`

```elixir
@spec lease_lost(GenServer.name(), atom()) :: :ok
```

Signal to the lease manager that the lease was lost because of some external reason

# `machine_id`

```elixir
@spec machine_id(GenServer.name()) :: non_neg_integer()
```

Returns the currently leased machine ID.

# `start_link`

```elixir
@spec start_link([opt()]) :: GenServer.on_start()
```

Starts the lease manager, blocking until the initial lease is acquired (or `:acquire_timeout`
elapses, in which case `start_link/1` fails).

## Options

  * `:name` - registered name (default `NoNoncense.MachineId.LeaseManager`)
  * `:strategy` (required) - a module implementing the `NoNoncense.MachineId.Strategy` behaviour
  * `:strategy_opts` - passed as-is to the strategy's callbacks (default `[]`)
  * `:lease_duration` - the duration, in ms, to request from the strategy on every
    `acquire`/`renew` call (the strategy may grant a different actual duration; default 8 hours)
  * `:renew_interval` - how often to renew, in ms; should be comfortably shorter than the
    lease's actual TTL to allow for retries (default 30 minutes)
  * `:acquire_timeout` - max total time, in ms, to keep retrying acquisition at boot before giving up
    and failing `start_link/1` (default `60_000`; pass `:infinity` to retry forever)
  * `:on_lease_lost` - called with the reason for the lease loss. Can be used to halt the entire node, for example. Note that on lease loss, all NoNoncense factories are always disabled to preserve uniqueness guarantees.

### Lease duration and renew interval

The defaults leave a wide recovery window for a temporary connection loss to your coordinator
(e.g. your database), while still renewing well ahead of the lease's expiration. If you
override these, keep that balance intact - most practical uses of nonce generation, such as
ID generation, will grind to a halt if generation stops, so favor conservative, generous
durations over aggressive, short ones. Machine IDs are meant to stay static for the lifetime
of the node, so there's little to be gained from renewing more aggressively.

---

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