# `Snowflakex`
[🔗](https://github.com/meetnow/snowflakex/blob/v1.2.0/lib/snowflakex.ex#L4)

Generates unique, roughly time-ordered 64-bit ID numbers ("snowflakes")
without coordination between nodes.

Snowflakex is modeled after Twitter's Snowflake. Every ID is a positive
integer composed of (from most to least significant bit):

  * 1 unused sign bit, always `0`
  * 41 bits timestamp in milliseconds since the Snowflakex epoch
    (`2016-12-05T08:51:41.749Z`), which lasts for about 69 years
  * 10 bits machine id, allowing up to 1024 generating nodes
  * 12 bits sequence number, allowing up to 4096 IDs per millisecond and node

## Configuration

Every node generating IDs needs a machine id between `0` and `1023` that is
unique among all nodes:

    config :snowflakex, machine_id: 123

The application refuses to start without a valid machine id.

## Usage

    iex> {:ok, id} = Snowflakex.new()
    iex> is_integer(id)
    true

# `components`

```elixir
@type components() :: %{timestamp: integer(), machine_id: 0..1023, sequence: 0..4095}
```

The components of a snowflake, as returned by `decompose/1`.

# `t`

```elixir
@type t() :: non_neg_integer()
```

A snowflake ID, a non-negative integer of at most 63 bits.

# `decompose`

```elixir
@spec decompose(t()) :: components()
```

Splits a snowflake into its components.

The `:timestamp` is given in milliseconds since the Unix epoch and can be
converted with `DateTime.from_unix!(timestamp, :millisecond)`.

## Examples

    iex> Snowflakex.decompose(4_194_476_039)
    %{timestamp: 1_480_927_902_749, machine_id: 42, sequence: 7}

    iex> id = Snowflakex.new!()
    iex> %{machine_id: 42} = Snowflakex.decompose(id)

# `epoch`

```elixir
@spec epoch() :: pos_integer()
```

Returns the Snowflakex epoch in milliseconds since the Unix epoch.

## Examples

    iex> Snowflakex.epoch() |> DateTime.from_unix!(:millisecond)
    ~U[2016-12-05 08:51:41.749Z]

# `max_machine_id`

```elixir
@spec max_machine_id() :: pos_integer()
```

Returns the highest machine id that can be configured.

# `new`

```elixir
@spec new() :: {:ok, t()} | {:error, String.t()}
```

Obtains a new snowflake.

Returns `{:ok, snowflake}` or `{:error, message}`, the latter only when the
system clock moved backwards since the last ID was generated.

## Examples

    iex> {:ok, id} = Snowflakex.new()
    iex> id > 0
    true

# `new!`

```elixir
@spec new!() :: t()
```

Obtains a new snowflake.

Raises `Snowflakex.ClockError` when the system clock moved backwards since
the last ID was generated.

## Examples

    iex> id = Snowflakex.new!()
    iex> id > 0
    true

---

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