From f7668ee3637327de5d0e2bd57687fe750bc95176 Mon Sep 17 00:00:00 2001 From: matt Date: Thu, 21 Nov 2019 16:22:24 -0800 Subject: [PATCH] Adds semantic typing information - `Snowflake.t` to represent snowflake ids - `Snowflake.epoch_timestamp` to represent a timestamp in the epoch - `Snowflake.unix_timestamp` classic Unix timestamp --- lib/snowflake.ex | 20 ++++++++++++++++++-- lib/snowflake/util.ex | 12 ++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/lib/snowflake.ex b/lib/snowflake.ex index 0333395..7b899a1 100644 --- a/lib/snowflake.ex +++ b/lib/snowflake.ex @@ -4,6 +4,22 @@ defmodule Snowflake do """ use Application + @typedoc """ + Snowflakes are unique IDs generated by combining the current epoch time and + the generating machine ID. + """ + @type t :: non_neg_integer + + @typedoc """ + Number of milliseconds since January 1, 1970, Midnight + """ + @type unix_timestamp :: non_neg_integer + + @typedoc """ + Number of milliseconds since the beginning of the configured epoch + """ + @type epoch_timestamp :: non_neg_integer + def start(_type, _args) do import Supervisor.Spec @@ -16,9 +32,9 @@ defmodule Snowflake do @doc """ Generates a snowflake ID, each call is guaranteed to return a different ID - that is sequantially larger than the previous ID. + that is sequentially larger than the previous ID. """ - @spec next_id() :: {:ok, integer} | + @spec next_id() :: {:ok, t} | {:error, :backwards_clock} def next_id() do GenServer.call(Snowflake.Generator, :next_id) diff --git a/lib/snowflake/util.ex b/lib/snowflake/util.ex index b9ede10..ea3825c 100644 --- a/lib/snowflake/util.ex +++ b/lib/snowflake/util.ex @@ -11,12 +11,12 @@ defmodule Snowflake.Util do @doc """ First Snowflake for timestamp, useful if you have a timestamp and want - to find snowflakes before or after a certain millesecond + to find snowflakes before or after a certain millisecond """ - @spec first_snowflake_for_timestamp(integer) :: integer + @spec first_snowflake_for_timestamp(Snowflake.unix_timestamp()) :: Snowflake.t() def first_snowflake_for_timestamp(timestamp) do ts = timestamp - Snowflake.Helper.epoch() - + << new_id :: unsigned-integer-size(64)>> = << ts :: unsigned-integer-size(42), 0 :: unsigned-integer-size(10), @@ -28,7 +28,7 @@ defmodule Snowflake.Util do @doc """ Get timestamp in ms from your config epoch from any snowflake ID """ - @spec timestamp_of_id(integer) :: integer + @spec timestamp_of_id(Snowflake.t()) :: Snowflake.epoch_timestamp() def timestamp_of_id(id) do id >>> 22 end @@ -36,7 +36,7 @@ defmodule Snowflake.Util do @doc """ Get timestamp from computer epoch - January 1, 1970, Midnight """ - @spec real_timestamp_of_id(integer) :: integer + @spec real_timestamp_of_id(Snowflake.t()) :: Snowflake.unix_timestamp() def real_timestamp_of_id(id) do timestamp_of_id(id) + Snowflake.Helper.epoch() end @@ -44,7 +44,7 @@ defmodule Snowflake.Util do @doc """ Get bucket value based on segments of N days """ - @spec bucket(integer, atom, integer) :: integer + @spec bucket(integer, atom, Snowflake.t()) :: integer def bucket(units, unit_type, id) do round(timestamp_of_id(id) / bucket_size(unit_type, units)) end