Chronicle.Captures.Capture (cratis_chronicle v3.16.1)

Copy Markdown View Source

DSL for defining discoverable Chronicle captures.

A capture turns data that arrives from outside the event log — an external API, a webhook, or another event store's public events — into events appended to this event store. The DSL compiles at build time to Capture Declaration Language (CDL) text, the same text format the Chronicle kernel's Workbench and SaveCapture accept.

Example

defmodule MyApp.Captures.InvoiceCapture do
  use Chronicle.Captures.Capture, name: "InvoiceCapture"

  api_source "InvoicingApi", route: "/invoices", poll: "10m"

  key "id"

  append MyApp.Events.InvoiceStatusChanged, when: "status" do
    set :status, "$.status"
  end
end

Options for use Chronicle.Captures.Capture

  • :name — the capture's name. Defaults to the module's last segment.
  • :id — the capture's stable id (a GUID string). Defaults to a deterministic UUIDv5 derived from the module's full name, so re-registering the same module updates the same kernel-side capture instead of creating a new one.
  • :start — when true, Chronicle.Captures.Registrar starts the capture after registering it (opt-in; defaults to false, leaving a freshly saved capture stopped).

Sources (exactly one is required)

Only api_source and events_source captures are run by the Chronicle engine as of Chronicle 19.6; see the CDL documentation linked above.

Key

key/1 names the property path (on the captured item) used to identify and diff it between observations. For an events_source, use "$eventSourceId" to key on the incoming event's event source.

Map (optional)

map do ... end declares operations applied to the captured item before append reads it:

map do
  rename :full_name, :fornavn
  template :greeting, "Hello, ${fornavn}"
  translate :status, :status, [{"aktiv", "active"}, {"inaktiv", "inactive"}]
  split :full_name, by: ",", into: [:first_name, :last_name]
end

Append

The kernel's CDL parser requires an append's event type to start with an uppercase letter (letters, digits, and underscores only - no hyphens), even though it is otherwise free to register event types with any id. Register the event type you intend to append from a capture with a matching id (id: "InvoiceStatusChanged" rather than id: "invoice-status-changed"); append/2,3 raises ArgumentError at compile time otherwise, rather than letting the capture fail validation on the kernel.

append/2,3 declares an event to append when its when: condition matches. set/2 inside its block maps a target field of the event's struct from a source expression ("$.path" for the current payload, "$previous.path" for the previous one, "$context.<property>" for the capture/event context, "$env.VARIABLE" for an environment lookup):

append MyApp.Events.CustomerChanged, when: {:any, ["firstName", "lastName"]} do
  set :first_name, "$.firstName"
end

when: accepts:

  • a string — when: "status" (fires when that property changes)
  • {:any, [...]} / {:all, [...]} — "p1 or p2" / "p1 and p2"
  • {:transition, property, from, to} — "status from a to b"
  • :added / :removed
  • {:expression, "template"} — a raw CDL expression

Nested and children scopes

nested :billing_address do
  map do
    rename :street, :"fakturaAdresse.gate"
  end

  append MyApp.Events.BillingAddressChanged, when: "street" do
    set :street, "$.street"
  end
end

children :line_items, identified_by: :line_number do
  append MyApp.Events.ItemAdded, when: :added do
    set :line_number, "$.lineNumber"
  end
end

Introspection

MyApp.Captures.InvoiceCapture.__chronicle_capture__(:id)
MyApp.Captures.InvoiceCapture.__chronicle_capture__(:name)
MyApp.Captures.InvoiceCapture.__chronicle_capture__(:declaration)

Registering with Chronicle.Client

{Chronicle.Client,
  ...
  captures: [MyApp.Captures.InvoiceCapture]}

Or use otp_app: auto-discovery — modules that export __chronicle_capture__/1 are discovered automatically. See Chronicle.Captures.Registrar for how registration happens.

Summary

Functions

Declares an API source, polling the named External Service.

Appends an event when its when: condition matches. See the moduledoc.

Declares a child collection scope, identified by a per-item key. See the moduledoc.

Declares an events source, capturing from the public events of another event store.

Names the property path used to identify and diff a captured item.

Declares map operations for the capture's root scope. See the moduledoc.

Declares a nested object scope. See the moduledoc.

Declares an inbound webhook source at the given path.

Functions

api_source(api, opts \\ [])

(macro)

Declares an API source, polling the named External Service.

append(event_module, opts \\ [], list)

(macro)

Appends an event when its when: condition matches. See the moduledoc.

children(collection_path, opts, list)

(macro)

Declares a child collection scope, identified by a per-item key. See the moduledoc.

events_source(events)

(macro)

Declares an events source, capturing from the public events of another event store.

events is a list of registered Chronicle.Events.EventType modules.

key(property_path)

(macro)

Names the property path used to identify and diff a captured item.

map(list)

(macro)

Declares map operations for the capture's root scope. See the moduledoc.

nested(object_path, list)

(macro)

Declares a nested object scope. See the moduledoc.

webhook_source(path)

(macro)

Declares an inbound webhook source at the given path.