View Source LibEcto.Ksuid (lib_ecto v0.2.4)

ksuid is a zero dependency Elixir library for generating and parsing KSUIDs. Read more about ksuid here

ksuid stands for K-Sortable Unique Identifier. It's a way to generate globally unique IDs which are partially chronologically sortable.

How To


iex> LibEcto.Ksuid.generate()
"0p9kxW1vWavpdq7VSgbv8piY0nr"

iex> LibEcto.Ksuid.parse("0p9kxW1vWavpdq7VSgbv8piY0nr")
{
  :ok,
  %DateTime{calendar: Calendar.ISO, day: 9, hour: 14, microsecond: {0, 0},
    minute: 52, month: 6, second: 34, std_offset: 0, time_zone: "Etc/UTC",
    utc_offset: 0, year: 2017, zone_abbr: "UTC"},
  <<166, 90, 80, 117, 89, 88, 196, 168, 113, 163, 157, 217, 224, 51, 151, 227>>
 }

Example Ecto Usage

Ecto Type

defmodule LibEcto.KsuidType do
  @moduledoc """
  types for ksuid
  uses string/varchar as storage type.
  """

  @behaviour Ecto.Type
  alias LibEcto.Ksuid

  def type, do: :string

  def cast(ksuid) when is_binary(ksuid), do: {:ok, ksuid}
  def cast(_), do: :error

  @doc """
  Same as `cast/1` but raises `Ecto.CastError` on invalid arguments.
  """
  def cast!(value) do
    case cast(value) do
      {:ok, ksuid} -> ksuid
      :error -> raise Ecto.CastError, type: __MODULE__, value: value
    end
  end

  def load(ksuid), do: {:ok, ksuid}

  def dump(binary) when is_binary(binary), do: {:ok, binary}
  def dump(_), do: :error

  # Callback invoked by autogenerate fields - this is all that really matters
  # just passing around the binary otherwise.
  @doc false
  def autogenerate, do: Ksuid.generate()
end

Usage in a Schema

:inserted_at is a virtual field that can be derived/loaded from the autogenerated :id

defmodule TestSchema do
  use Ecto.Schema

  @primary_key {:id, KsuidType, autogenerate: true}
  schema "test" do
    field :name, :string
    field :inserted_at, :utc_datetime, virtual: true
  end

  def inserted_at(%TestSchema{id: ksuid} = row) do
     {:ok, time_stamp, _} = LibEcto.Ksuid.parse(ksuid)
     %TestSchema{row | inserted_at: time_stamp}
  end
  
end

Migration

Create :id as :bytea, and primary key - similary to usage with :binary_id

  def change do
     create table(:test, primary_key: false) do
      add :id, :string, primary_key: true, size: 27
      add :name, :text
     
    end
  end

Summary

Functions

This method returns a 20 byte Ksuid which has 4 bytes as timestamp and 16 bytes of crypto string bytes.

Functions

@spec generate() :: binary()

This method returns a 20 byte Ksuid which has 4 bytes as timestamp and 16 bytes of crypto string bytes.

Examples

iex> Ksuid.generate()
"0KZi94b2fnVzpGi60FoZgXIvUtYy"
@spec parse(binary()) :: {:ok, NaiveDateTime.t(), binary()} | {:error, any()}