See [https://hexdocs.pm/flake_id](https://hexdocs.pm/flake_id) for the complete documentation.
### With Ecto
It is possible to use `FlakeId` with [`Ecto`](https://github.com/elixir-ecto/ecto/).
See [`FlakeId.Ecto.Type`](https://hexdocs.pm/flake_id/FlakeId.Ecto.Type.html) documentation for detailed instructions.
If you wish to migrate from integer serial ids to Flake, see [`FlakeId.Ecto.CompatType`](https://hexdocs.pm/flake_id/FlakeId.Ecto.Type.html) for instructions.
## Prior Art
* [flaky](https://github.com/nirvana/flaky), released under the terms of the Truly Free License,
* [Flake](https://github.com/boundary/flake), Copyright 2012, Boundary, Apache License, Version 2.0
# Matches when time didn't change and sequence is too big for 16bit int.
def get(newtime, %__MODULE__{time: time, sq: sq}) when newtime == time and sq >= 65_535 do
{:error, :clock_stuck}
end
# Matches when the calling time is the same as the state time. Incr. sq
def get(time, %__MODULE__{node: node, time: time, sq: seq} = state) when is_integer(time) and is_integer(node) and is_integer(seq) do
new_state = %__MODULE__{state | sq: state.sq + 1}
- {gen_flake(new_state), new_state}
+ {:ok, gen_flake(new_state), new_state}
end
# Matches when the times are different, reset sq
def get(newtime, %__MODULE__{node: node, time: time, sq: seq} = state) when is_integer(time) and is_integer(node) and is_integer(seq) and newtime > time do
The compat type allows to keep your old ids as they used to look before, while the newest ones will be fully fledged flakes.
This works by altering your ids columns from serial/int/bigint to an UUID, while rewriting the UUID to look like a zero-padded plus the old integer number.
Such a feat can be accomplished in your migration by using:
ALTER COLUMN user_id SET DATA TYPE uuid USING CAST( LPAD( TO_HEX(user_id), 32, '0' ) AS uuid)
A full example of a migration can be found on [Pleroma's code](https://git.pleroma.social/pleroma/pleroma/-/blob/develop/priv/repo/migrations/20181218172826_users_and_activities_flake_id.exs).
"""
import Kernel, except: [to_string: 1]
@behaviour Ecto.Type
def embed_as(_), do: :self
def equal?(term1, term2), do: term1 == term2
def type, do: :uuid
- defdelegate autogenerate, to: FlakeId, as: :get
+ defdelegate autogenerate, to: FlakeId.Ecto.Type, as: :autogenerate