SnowflakeId (snowflake_id v0.1.0)

Generates SnowflakeId's. This struct implements the Enumerable protocol, so you can use this with all the functions from Enum and Stream modules.

This implementation is functional and does not use any GenServer to store the state.

# override the time function for the test
iex> get_time = fn -> 1630163558780 end
iex> generator = SnowflakeId.new(1, 1, get_time: get_time)
iex> Enum.at(generator, 0)
6837401535245324288
iex> generator |> Enum.at(0) |> Integer.to_string(2)
"101111011100011010101000111100001011111000000100001000000000000"
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^xxxxxyyyyyzzzzzzzzzzzz
#^: timestamp
#x: machine_id
#y: node_id
#z: index

More realistic example:

iex> my_data =
...>   SnowflakeId.new(1, 1)
...>   |> Enum.take(10)
...>   |> Enum.map(fn id ->
...>     # insert your data in your database
...>     %{id: id, name: "my_id_#{id}"}
...>   end)
iex> length(my_data)
10

If you want to not use the Enumerable protocol you can do it yourself by:

# override the time function for the test
iex> get_time = fn -> 1630163558780 end
iex> generator = SnowflakeId.new(1, 1, get_time: get_time)
iex> SnowflakeId.format_id(generator)
6837401535245324288
iex> generator = SnowflakeId.next(generator)
iex> SnowflakeId.format_id(generator)
6837401535245324289

Link to this section Summary

Functions

Format the struct to return a id

Update the struct to the next identifier

Default function to return the current timestamp in milliseconds

Create a new SnowflakeId struct but with some extra checks. For more info check new/3

Link to this section Types

Specs

opts() :: [bulk: boolean(), get_time: (() -> integer())]

Specs

t() :: %SnowflakeId{
  bulk: boolean(),
  get_time: (() -> integer()),
  idx: integer(),
  last_time_millis: integer(),
  machine_id: integer(),
  node_id: integer()
}

Link to this section Functions

Link to this function

format_id(snowflake_id)

Specs

format_id(t()) :: integer()

Format the struct to return a id

Link to this function

new(machine_id, node_id, opts \\ [])

Specs

new(integer(), integer(), opts()) :: t()

Create a new SnowflakeId struct

options:

  • :get_time : (-> integer) override the function to get the current timestamp, this function should return the time since an epoch in milliseconds. by defaut it uses :os.system_time(:millisecond)

  • :bulk : boolean Don't check the time on every iteration, but only when the maximum amount of indexes is filled, which is 0..4095 This can be handy if you know you are going to generate a lot of indexes at once.

Specs

next(t()) :: t()

Update the struct to the next identifier

Link to this function

os_system_time()

Specs

os_system_time() :: integer()

Default function to return the current timestamp in milliseconds

Link to this function

try_new(machine_id, node_id, opts \\ [])

Specs

try_new(integer(), integer(), opts()) :: {:ok, t()} | {:error, atom()}

Create a new SnowflakeId struct but with some extra checks. For more info check new/3