A binding: the declaration that routes an event from a source to one execution of one document, as ADR-0001 fixes it.
A binding says which events it wants (match), how to compute the key
that names one execution among many (key), which document that
execution belongs to (document), which chart event the execution is
handed (event), and which fields of the event travel with it (data).
Construction
new/1 takes a map or keyword list whose keys are atoms from this table
(ADR-0001, section 1) and returns {:ok, binding} or {:error, reason}:
| Key | Value | Default |
|---|---|---|
:id | a non-empty string | required |
:source | a string | required |
:selector | a map | %{} |
:match | a predicator program, as a string | required |
:key | a predicator program, as a string | required |
:document | a non-empty string | required |
:event | a non-empty string | required |
:data | a list of dotted field paths, as strings | [] |
:create | :if_absent, :never or :always_new | :if_absent |
:dedupe | %{by: :message_id, horizon_ms: h}, h a positive integer | %{by: :message_id, horizon_ms: 259_200_000} |
:order | :by_key or :none | :by_key |
:enabled | a boolean | true |
Every fault that can be seen without an event is refused here, in this
order: a reserved key (mode, batch or window, ADR-0001 section 6)
before any other check, then an unknown key, then a missing required key,
then a value the table does not allow, then a match or key that
predicator does not compile (ADR-0001 section 2). match and key are
compiled once, here, and kept compiled.
A duplicate id among several bindings is a fault of the configuration
that holds them, not of one binding, so new/1 does not look for it.
Evaluation
match/2 and key/2 evaluate the compiled programs over the normalized
event, a string-keyed map bound in the predicator context as event, so
a program reads event.kind or event.impression_id.
match/2returnstrueonly when the program evaluates to exactlytrue.falseandnilreturnfalse, and:undefinedreturns:undefined: all three mean the event is not for this binding. An evaluation error, or any other value, is{:refused, reason}(ADR-0001 section 2).key/2returns{:ok, key}when the program evaluates to a non-empty string, and{:refused, reason}for anything else (ADR-0001 section 3).
project/2 builds the delivered event's data from the data paths
(ADR-0001 section 5).
Example
iex> {:ok, binding} =
...> StatifierRouter.Binding.new(
...> id: "clicks_to_join",
...> source: "ad_events",
...> match: "event.kind == 'click'",
...> key: "event.impression_id",
...> document: "impression_click_join",
...> event: "click",
...> data: ["impression_id", "url"]
...> )
iex> click = %{"kind" => "click", "impression_id" => "imp_7f3a"}
iex> StatifierRouter.Binding.match(binding, click)
true
iex> StatifierRouter.Binding.key(binding, click)
{:ok, "imp_7f3a"}
iex> StatifierRouter.Binding.project(binding, click)
%{"impression_id" => "imp_7f3a"}
Summary
Types
Why new/1 refused a binding.
A predicator instruction list, as Predicator.compile/1 returns it.
Functions
Evaluates the binding's key over the normalized event.
Evaluates the binding's match over the normalized event.
Builds a binding from a map or keyword list with atom keys, validating
every key and value and compiling match and key once.
Builds the delivered event's data: each of the binding's data paths,
read from the normalized event and written under the same path.
Types
@type new_error() :: {:reserved_key, term()} | {:unknown_key, term()} | {:duplicate_key, atom()} | {:missing_key, atom()} | {:invalid_value, atom(), term()} | {:match, struct()} | {:key, struct()} | {:invalid_binding, term()}
Why new/1 refused a binding.
@type program() :: list()
A predicator instruction list, as Predicator.compile/1 returns it.
@type t() :: %StatifierRouter.Binding{ compiled_key: program(), compiled_match: program(), create: :if_absent | :never | :always_new, data: [String.t()], dedupe: %{by: :message_id, horizon_ms: pos_integer()}, document: String.t(), enabled: boolean(), event: String.t(), id: String.t(), key: String.t(), match: String.t(), order: :by_key | :none, selector: map(), source: String.t() }
Functions
Evaluates the binding's key over the normalized event.
Returns {:ok, key} when the program evaluates to a non-empty string.
Anything else - :undefined, nil, the empty string, a number, any other
value, or an evaluation error - is {:refused, reason}.
Evaluates the binding's match over the normalized event.
Returns true when the program evaluates to exactly true; false when
it evaluates to false or nil; :undefined when it evaluates to
:undefined. The last two mean the event is not for this binding.
Returns {:refused, reason} when the evaluation returns an error or any
other value.
Builds a binding from a map or keyword list with atom keys, validating
every key and value and compiling match and key once.
Returns {:ok, binding}, or {:error, reason} naming the first fault
found, in the order the moduledoc gives.
Builds the delivered event's data: each of the binding's data paths,
read from the normalized event and written under the same path.
A dotted path reads and writes nested maps, so "placement.slot" carries
%{"placement" => %{"slot" => value}}. A path the event does not carry
is left out, and nothing outside the listed paths is delivered.