lib/toolbox/incident/id_generator.ex

defmodule Toolbox.Incident.IdGenerator do
  @moduledoc """
  Module provides functions to generate incident id.
  """

  @doc """
  Generates full incident ID based on incident type, timestamp and serialization vector.

  Serialization vector is list of relevant attributes which together with type and timestamp
  uniquely identify given incident.

  Note including maps in serialization vector increases a risk the ID will change on new major OTP
  version. If you strongly prefer long-term stability avoid maps. This uses
  `:erlang.term_to_binary` under the hood.

  This function is deprecated as it returns the full ID that includes type. This is no longer very
  useful as Output Actions take type and ID separately. Use `generate_id/3` instead.

  ## Examples

        iex> Toolbox.Incident.IdGenerator.generate("/incident/type", 0123456789, ["/asset/type/1"])
        "/incident/type/f4c3877a-d50b-3a16-b6ec-3ebb2b308d40"

  """
  @doc deprecated: "Use generate_id/3 instead"
  def generate(incident_type, timestamp, vector) do
    generated =
      UUID.uuid3(
        nil,
        :erlang.term_to_binary([incident_type, timestamp, vector], [
          :deterministic,
          {:minor_version, 1}
        ])
      )

    if String.ends_with?(incident_type, "/") do
      "#{incident_type}#{generated}"
    else
      "#{incident_type}/#{generated}"
    end
  end

  @doc """
  Generates incident ID based on incident type, timestamp and serialization vector.

  Serialization vector is list of relevant attributes which together with type and timestamp
  uniquely identify given incident.

  Note including maps in serialization vector increases a risk the ID will change on new major OTP
  version. If you strongly prefer long-term stability avoid maps. This uses
  `:erlang.term_to_binary` under the hood.

  This function is compatible with deprecated `generate/3`, you can replace it with this and the IDs
  will not change.

  ## Examples

        iex> Toolbox.Incident.IdGenerator.generate_id("/incident/type", 0123456789, ["/asset/type/1"])
        "f4c3877a-d50b-3a16-b6ec-3ebb2b308d40"
  """
  @doc since: "5.2.0"
  def generate_id(incident_type, timestamp, vector) do
    UUID.uuid3(
      nil,
      :erlang.term_to_binary([incident_type, timestamp, vector], [
        :deterministic,
        {:minor_version, 1}
      ])
    )
  end
end