View Source Runbox.Runtime.Stage.UnitRegistry (runbox v17.1.0)

Unit register used in stage based runtime to manage state of units.

UnitRegistry is configured via Runbox.Scenario.Template.StageBased.subscriptions/0 callback result. Callback returns template subscriptions, each subscription is defined as {message_type, routing_rule}. Unit registry contains one register per configured message_type. Routing rule is used to store unit and later on lookup this unit when needed.

Units are being registered using unit attributes as defined in routing_rule. Unit lookup uses routing_rule to parse message body and the result compares to stored unit attributes.

Summary

Functions

Returns unit with given id.

Initialize UnitRegistry non-persisted fields.

Searches for registered unit in the unit registry.

Creates new unit registry.

Returns first reached timeout and removes it from unit registry in one operation.

Registers given unit to the unit registry.

Reregisters unit in the unit registry.

Unregisters given unit from the unit registry.

Updates unit in unit registry.

Upgrades a possibly old version of the struct to the current version.

Types

@type msg_parser() :: (Runbox.Message.t() -> routing_key())
@type path() :: [String.t() | atom()]
@type routing_key() :: [String.t()]
@type routing_key_def() :: {:=, [path()], [path()]} | {:in, [path()], [path()]}
@type t() :: %Runbox.Runtime.Stage.UnitRegistry{
  alt_regs: %{
    required(Runbox.Message.type()) => %{required(routing_key()) => unit_id()}
  },
  config: [{Runbox.Message.type(), routing_key_def()}],
  parse_msg_fns: %{required(Runbox.Message.type()) => msg_parser()},
  register_unit_fns: %{required(Runbox.Message.type()) => unit_register()},
  runbox_version: Version.t(),
  timeouts: [
    {Runbox.StateStore.ScheduleUtils.epoch_ms(), unit_id(), Runbox.Message.t()}
  ],
  units: %{required(unit_id()) => Runbox.Runtime.Stage.Unit.t()}
}
@type unit_id() :: String.t()
@type unit_register() :: (map(),
                    Runbox.Message.type(),
                    Runbox.Runtime.Stage.Unit.t() ->
                      map())

Functions

Link to this function

get_unit(unit_registry, id)

View Source
@spec get_unit(t(), unit_id()) ::
  {:ok, Runbox.Runtime.Stage.Unit.t()} | {:error, :not_found}

Returns unit with given id.

@spec init(t()) :: t()

Initialize UnitRegistry non-persisted fields.

This needs to be called right before starting new unit registry (done in new/1 automatically) and also after loading UnitRegistry from savepoint. This is needed because not all fields are persisted into a savepoint.

Link to this function

lookup(unit_registry, msg)

View Source
@spec lookup(t(), Runbox.Message.t()) ::
  {:ok, [Runbox.Runtime.Stage.Unit.t()]} | {:error, :unknown_message_type}

Searches for registered unit in the unit registry.

@spec new([{Runbox.Message.type(), routing_key_def()}]) :: t()

Creates new unit registry.

Link to this function

pop_reached_timeout(unit_registry, ts)

View Source
@spec pop_reached_timeout(t(), Runbox.StateStore.ScheduleUtils.epoch_ms()) ::
  {:ok, Runbox.Runtime.Stage.Unit.t(), Runbox.Message.t(), t()}
  | :no_reached_timeout

Returns first reached timeout and removes it from unit registry in one operation.

Link to this function

register(unit_registry, unit)

View Source
@spec register(t(), Runbox.Runtime.Stage.Unit.t()) :: t()

Registers given unit to the unit registry.

Link to this function

register_timeout(unit_registry, unit, ts, msg)

View Source

Registers timeout.

Link to this function

reregister(unit_registry, unit)

View Source
@spec reregister(t(), Runbox.Runtime.Stage.Unit.t()) :: t()

Reregisters unit in the unit registry.

Function updates alternative registers using new version of unit attributes. Timeouts will remain untouched.

Link to this function

unregister(unit_registry, unit)

View Source
@spec unregister(t(), Runbox.Runtime.Stage.Unit.t()) :: t()

Unregisters given unit from the unit registry.

Link to this function

update(unit_registry, unit)

View Source
@spec update(t(), Runbox.Runtime.Stage.Unit.t()) :: {:ok, t()} | {:error, :not_found}

Updates unit in unit registry.

@spec upgrade(old_unit_reqistry :: any()) :: t()

Upgrades a possibly old version of the struct to the current version.

The upgrade process is based on steps. Each step applies transformation of the state related to the changes in a specific version. It is similar to database migrations. This function executes all the upgrade steps since the version of the given struct until the struct is upgraded to the current version.

Adding a new upgrade step

For example, if version 42.0.0 adds the field :new_field, then you should create a corresponding clause in the do_upgrade_step/1 function. This clause should upgrade the state from the last preceding version (e.g., 41.1.0) and update the :runbox_version field. Like so:

defp do_upgrade_step(%{runbox_version: %{major: major}} = snapshot) when major < 42 do
  snapshot
  |> Map.put(:new_field, :some_value)
  |> Map.put(:runbox_version, Version.parse!("42.0.0"))
end

Place this new clause right before the catch-all clause (defp do_upgrade_step(snapshot)).