README.md

# ExKsuid

[![Build Status](https://github.com/calvinsadewa/ex_ksuid/workflows/Elixir%20CI/badge.svg)](https://github.com/calvinsadewa/ex_ksuid/actions)

Fully featured KSUID module in Elixir

KSUID (K-Sortable unique ID) is a way to generate ID (like to UUID), which use 4 byte of timestamp and 16 byte of random data. \
KSUID can be lexicographically sort for rough ordering (at second resolution) of when KSUID is generated, in DB, sorting by KSUID as primary key usually faster than sorting `inserted_at` or `updated_at`

Example:
>Example (KSUID in Base62)
1czONudbZwh5siu2igQJY94QkFH

This module can:
- Generate KSUID in Base62/Raw byte format, with specific input on timestamp & random payload 
- Parse KSUID to get it's timestamp part and random payload part
- Provide Ecto Schema basic Type for use as field/primary key, either in Base62 or Raw byte

more information on https://github.com/segmentio/ksuid

## Common Usage
```
# Generate KSUID (simple)
ExKsuid.generate()
## 1czONudbZwh5siu2igQJY94QkFH

# Parse information in KSUID
result = ExKsuid.parse("1czONudbZwh5siu2igQJY94QkFH")
## %{
##   random_bytes: <<78, 137, 74, 76, 6, 99, 179, 98, 179, 99, 109, 200, 247, 175,
##     171, 187>>,
##   timestamp: 1591527918
## }
DateTime.from_unix(result.timestamp)
## {:ok, ~U[2020-06-07 11:05:18Z]}

# Filter all KSUID after 2020-02-15 timestamp
data = [~U[2020-01-01 00:00:00Z], ~U[2020-02-01 00:00:00Z], ~U[2020-03-01 00:00:00Z], ~U[2020-04-01 00:00:00Z], ~U[2020-05-01 00:00:00Z]]
data = data |> Enum.map(& ExKsuid.generate(timestamp: &1 |> DateTime.to_unix()))
## ["1Vlny8xRAj9lht9c0DsxpbBK8Gi", "1XBMnOgQG7Gm7S63kPjiW0EqIlM",
## "1YVHNQAFJsvQgtQvcLlpdeW1FCY", "1ZuqCjUj9tluPXTyU2q45w3ZwiW",
## "1bHZuH1adLPe8PjgHwYz7JPHVHx"]
ksuid = ExKsuid.generate(timestamp: ~U[2020-02-15 00:00:00Z] |> DateTime.to_unix())
## 1XouWeBxLmlTwhaLqOu4a7SPLp7
data |> Enum.filter(fn d -> d > ksuid end) |> Enum.map(fn d -> 
  result = ExKsuid.parse(d)
  DateTime.from_unix!(result.timestamp)
end)
## [~U[2020-03-01 00:00:00Z], ~U[2020-04-01 00:00:00Z], ~U[2020-05-01 00:00:00Z]]

# Use in Ecto Schema
defmodule Account do
  use Ecto.Schema

  @primary_key {:ksuid, ExKsuid.EctoType, autogenerate: true}
  schema "account" do
    field :name, :string
    field :email, :string
  end
end
```

## Comparison
[elixir-ksuid](https://github.com/girishramnani/elixir-ksuid) is established module for generating KSUID in elixir

`ExKsuid` get inspiration from `elixir-ksuid`. In comparison, ExKsuid has several advantage like:
- Generate KSUID based on timestamp & custom random source
- Generate Raw byte KSUID, which is smaller (20 byte) than usual base62 format (27 byte)



## Installation

The package can be installed
by adding `ex_ksuid` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:ex_ksuid, "~> 0.2.0"}
  ]
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/ex_ksuid](https://hexdocs.pm/ex_ksuid).