StatifierRouter.Config (StatifierRouter v0.1.0)

Copy Markdown View Source

The router's resolved configuration: the host's repo, where this package's tables live in it, the bindings events are routed by, the module each delivery is handed to, and what that module needs to reach statifier_persistence.

new/1 takes a keyword list and returns {:ok, config} or {:error, reason}:

OptionValueDefault
:repothe host's Ecto.Repo modulerequired
:deliverythe module StatifierRouter.route/3 hands each delivery toStatifierRouter.Delivery
:storea %StatifierPersistence.Storage{} built over the same reporequired by StatifierRouter.Delivery
:executorthe StatifierPersistence.Executor effects are handed to: a module or an arity-2 funrequired by StatifierRouter.Delivery
:resolverthe StatifierRouter.Resolver naming the chart a new execution starts on: a module implementing it or an arity-2 funrequired by StatifierRouter.Delivery
:chart_resolvera fun of (content_hash) compiling the chart an existing execution started onrequired by StatifierRouter.Delivery
:bindingsa list of bindings, each a map or keyword list StatifierRouter.Binding.new/1 accepts, or a %StatifierRouter.Binding{} it built[]
:table_prefixa string prefixed to every table name"statifier_router_"
:prefixthe Postgres schema the tables live in, as a stringnil (the repo's default)

StatifierRouter documents what a delivery module must answer, and StatifierRouter.Delivery what the four options it requires must be. A configuration that names another delivery module may leave those four out; one it gives is checked all the same.

Each binding is built with StatifierRouter.Binding.new/1, in the order given, and the resolved configuration keeps that order: it is the order StatifierRouter.route/3 returns its outcomes in. A duplicate binding id is a fault of the list rather than of any one binding, so it is refused here, naming the duplicated id, before any event is routed (ADR-0001, section 1).

The three tables are the address table of ADR-0002 (addresses), the dedupe table of ADR-0003 (dedupe) and the ledger of ADR-0004 (routing_ledger); table/2 names each one under a configuration. StatifierRouter.Migrations creates them from the same two storage options, and put_meta/2 and queryable/2 point the schemas in StatifierRouter.Schema at them, so the DDL and the rows cannot disagree on a name.

iex> {:ok, config} =
...>   StatifierRouter.Config.new(
...>     repo: MyApp.Repo,
...>     delivery: MyApp.Delivery,
...>     prefix: "routing"
...>   )
iex> StatifierRouter.Config.table(config, :addresses)
"statifier_router_addresses"
iex> config.prefix
"routing"

Summary

Types

The host's compiled chart for a content hash an existing execution records, or :error when it has none: the shape StatifierPersistence.Driver's chart_resolver: takes.

Why new/1 refused a configuration.

The host's answer to which chart a new execution of document starts on, under scope (ADR-0002, section 4): a module implementing StatifierRouter.Resolver, or an arity-2 fun with its callback's signature.

t()

One of the three tables this package owns.

Functions

Validates the options in the table above and resolves them into a configuration.

Points a row of one of the StatifierRouter.Schema modules at this configuration's table and Postgres schema, so that Repo.insert/2 writes it there.

A query over one of the StatifierRouter.Schema modules that reads this configuration's table in its Postgres schema.

The name of table under this configuration: the table prefix followed by the table's own name.

Types

chart_resolver()

@type chart_resolver() :: (content_hash :: String.t() ->
                       {:ok, Statifier.Machine.t()} | :error)

The host's compiled chart for a content hash an existing execution records, or :error when it has none: the shape StatifierPersistence.Driver's chart_resolver: takes.

new_error()

@type new_error() ::
  {:unknown_key, term()}
  | {:missing_key, :repo | :store | :executor | :resolver | :chart_resolver}
  | {:invalid_value, atom(), term()}
  | {:invalid_config, term()}
  | {:binding, non_neg_integer(), StatifierRouter.Binding.new_error()}
  | {:duplicate_binding_id, String.t()}

Why new/1 refused a configuration.

resolver()

@type resolver() :: StatifierRouter.Resolver.t()

The host's answer to which chart a new execution of document starts on, under scope (ADR-0002, section 4): a module implementing StatifierRouter.Resolver, or an arity-2 fun with its callback's signature.

t()

@type t() :: %StatifierRouter.Config{
  bindings: [StatifierRouter.Binding.t()],
  chart_resolver: chart_resolver() | nil,
  delivery: module(),
  executor: StatifierPersistence.Executor.t() | nil,
  prefix: String.t() | nil,
  repo: module(),
  resolver: resolver() | nil,
  store: StatifierPersistence.Storage.t() | nil,
  table_prefix: String.t()
}

table()

@type table() :: :addresses | :dedupe | :routing_ledger

One of the three tables this package owns.

Functions

new(opts)

@spec new(keyword()) :: {:ok, t()} | {:error, new_error()}

Validates the options in the table above and resolves them into a configuration.

Returns {:ok, config}, or {:error, reason} naming the first fault: an unknown option, then a missing or malformed :repo, then a malformed :delivery, then a missing or malformed :store, :executor, :resolver or :chart_resolver, in that order, then a storage value the table does not allow, then the first binding StatifierRouter.Binding.new/1 refuses, as {:binding, index, reason} with index counted from zero, then the first duplicated binding id.

iex> StatifierRouter.Config.new(repo: MyApp.Repo, delivery: MyApp.Delivery, table_prefix: 7)
{:error, {:invalid_value, :table_prefix, 7}}
iex> StatifierRouter.Config.new(repo: MyApp.Repo)
{:error, {:missing_key, :store}}

put_meta(config, row)

@spec put_meta(t(), struct()) :: struct()

Points a row of one of the StatifierRouter.Schema modules at this configuration's table and Postgres schema, so that Repo.insert/2 writes it there.

queryable(config, schema)

@spec queryable(t(), module()) :: Ecto.Query.t()

A query over one of the StatifierRouter.Schema modules that reads this configuration's table in its Postgres schema.

table(config, table)

@spec table(t(), table()) :: String.t()

The name of table under this configuration: the table prefix followed by the table's own name.