factos/factos_pog

PostgreSQL backend for Factos using the pog package.

This backend stores accepted facts in the append-only factos.factos_events table. The globally ordered event history is the source of truth; projections and other read models are application-owned derived views.

The dispatch flow follows Command Context Consistency: a command selects the facts required for its decision, folds them into temporary state, decides new facts, and appends only when no selected fact appeared after the observed context position.

Selective contexts use event types and tags. PostgreSQL stores JSON event data without understanding the domain payload, so any payload value needed for context selection must also be written as a tag.

Example

let configuration = factos_pog.configure(model, connection:)

configuration
|> factos_pog.dispatch(
  command,
  decision_context: decision_context(command),
  event_id: new_event_id,
)

Types

pub type Configuration(command, state, event, domain_error, subscription_error) {
  Configuration(
    model: factos.Model(command, state, event, domain_error),
    connection: pog.Connection,
    retry_attempts: Int,
    subscriptions: List(
      factos.Subscription(
        pog.Connection,
        factos.Recorded(event),
        subscription_error,
      ),
    ),
  )
}

Constructors

pub type Error(domain_error, subscription_error) =
  factos.Error(
    domain_error,
    subscription_error,
    pog.QueryError,
    json.DecodeError,
  )
pub type Subscription(event, error) =
  factos.Subscription(
    pog.Connection,
    factos.Recorded(event),
    error,
  )

Values

pub fn configure(
  model model: factos.Model(command, state, event, domain_error),
  connection connection: pog.Connection,
) -> Configuration(
  command,
  state,
  event,
  domain_error,
  subscription_error,
)
pub fn dispatch(
  configuration: Configuration(
    command,
    state,
    event,
    domain_error,
    subscription_error,
  ),
  command command: command,
  decision_context decision_context: factos.DecisionContext,
  event_id event_id: fn() -> String,
) -> Result(
  factos.Dispatch(event),
  factos.Error(
    domain_error,
    subscription_error,
    pog.QueryError,
    json.DecodeError,
  ),
)

Dispatch a command and atomically append its accepted events.

Search Document