Dmn.Run (dmn v0.1.0)

Copy Markdown View Source

Runs a compiled model.

The units that the decisions asked for need are run in the order of the plan (Dmn.Compiled.plan/2), each once: a unit gets the values of the units it reads as the bindings of its prepared expression, and gives its value to the units that read it. Nothing is parsed, resolved or typed here.

The inputs

The inputs are a map of the names of the input data to their values (or {namespace, name}, for the input data of a model that is imported), which are FEEL values (Feel.Value): numbers are Decimals, contexts are maps. An input that is not given is null. A value that does not fit the declared type or the allowed values of its input data is converted, or is null with an error, in every unit that reads it, as the declarations of FEEL say (D-138).

Errors

An error of an element (a type mismatch, a division by zero, a table that is broken) makes its value null and is a diagnostic, and the run goes on: DMN 1.6, 7.3.8, calls this :lenient. With mode: :strict the first error ends the run, and the result is {:error, %Dmn.Error{kind: :run, code: :strict}} with the diagnostic in its details. An element that could not be compiled (a text that does not parse, a cycle) is null with its errors, in both.

What is wrong with an element whatever the data (a requirement that names nothing, a name or an id that another element has, a type it declares that is not defined) is a fault of its unit: every run of a model that needs the element says it as a diagnostic, and a strict run ends on it. A run does not look at the elements it does not need, and does not say that a model is valid: that is Dmn.validate/1.

Recursion

The units of a recursion group (Dmn.Compiled.groups, Dmn.compile/2 with recursion: true) are run with links to the members they read instead of their values (Feel.Recursion): each is run when the plan reaches it, the links are made once for the group, and a call through one is a call of FEEL in the run it is made in, so Feel.Limits ends a recursion that does not end.

Options

:mode (:lenient or :strict), and, for the runs of FEEL, :clock, :entropy, :limits (Feel.Limits). A run keeps to the limits that the model was compiled with (:feel_limits of Dmn.compile/2) unless it is given :limits, which take their place. Only these keys and :mode are accepted by this internal execution module. Mode defaults to :lenient. The public Dmn.evaluate/4, Dmn.evaluate_all/4, Dmn.run/2 and Dmn.invoke/4 wrappers validate and consume :sandbox and :guard, then apply the shared Feel.Worker boundary. Calling this module directly does not start a worker. Unknown keys, repeated keys, malformed keyword lists and invalid modes return a run error with code :invalid_options.

Summary

Functions

Runs the decisions called names, with the inputs.

Calls a business knowledge model or a decision service of the model, as a function (DMN 1.6, 10.4): the arguments are a map of the names of the parameters to values, or a list of values in the order of the parameters.

Functions

evaluate(compiled, names, inputs, options \\ [])

@spec evaluate(Dmn.Compiled.t(), [String.t()], map(), keyword()) ::
  {:ok, Dmn.Result.t()} | {:error, Dmn.Error.t()}

Runs the decisions called names, with the inputs.

Returns the Dmn.Result, or an error of the kind :run: a name that is not a decision, a business knowledge model or a decision service of the model (a string, that is: anything else is none), or one that more than one element has (:unknown_decision, :ambiguous_name), names that are not a list, inputs that are not a map, or options that are not what they should be (:invalid_inputs, :invalid_options), or a run that ended in strict mode. Nothing raises for what the arguments are (DD-36), whether a caller built them or got them from outside.

invoke(compiled, name, arguments, options \\ [])

@spec invoke(Dmn.Compiled.t(), String.t(), map() | list(), keyword()) ::
  {:ok, Dmn.Result.t()} | {:error, Dmn.Error.t()}

Calls a business knowledge model or a decision service of the model, as a function (DMN 1.6, 10.4): the arguments are a map of the names of the parameters to values, or a list of values in the order of the parameters.

A map may have names that are not parameters (the inputs of a test, say): they are left out. The function value is made by running the elements it needs, as for a decision, and the call is a call of FEEL, so the arguments are converted to the types of the parameters, a missing argument is null, and the depth of calls is limited. Returns the Dmn.Result (with the value of the call under name).

Nothing raises for the model or the arguments: an element that is not a function (a decision, a business knowledge model that has no logic, or an external one that cannot be run) is an error :not_a_function, a name that is not a string is :unknown_decision, and arguments that are neither a map of names nor a list are :invalid_arguments.

An error of the call is the code of the error of FEEL (:limit_exceeded for a limit of Feel.Limits, as a decision that passes it has), or :feel_error where it has none, with details.kind the kind of it; :strict is that of an error in the :strict mode (DD-36).