factos/factos_sqlight

SQLite backend for Factos using the sqlight package.

This backend stores accepted facts in an append-only factos_events table. The globally ordered event history is the source of truth. Projection folds and effect derivation remain ordinary application functions.

Dispatch uses BEGIN IMMEDIATE. SQLite acquires the writer lock before the command context is read, so every accepted command observes and protects one stable event-log state through append, strong callbacks, and commit.

Example

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

configuration
|> factos_sqlight.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: sqlight.Connection,
    retry_attempts: Int,
    subscriptions: List(
      factos.Subscription(
        sqlight.Connection,
        factos.Recorded(event),
        subscription_error,
      ),
    ),
  )
}

Constructors

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

Values

pub fn configure(
  model model: factos.Model(command, state, event, domain_error),
  connection connection: sqlight.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,
    sqlight.Error,
    json.DecodeError,
  ),
)

Execute one configured dispatch against SQLite.

Dispatch uses BEGIN IMMEDIATE to read the request’s decision context, decide, append, and run subscriptions in one transaction. Codec, decision, and subscription functions must remain deterministic across retries.

pub fn migrate(
  connection: sqlight.Connection,
) -> Result(
  Nil,
  factos.Error(
    domain_error,
    subscription_error,
    sqlight.Error,
    json.DecodeError,
  ),
)

Create the fresh SQLite schema required by this backend.

Applications with existing databases should copy the statements into their own immutable migration history rather than using this convenience at startup.

pub fn sqlight_error_to_string(error: sqlight.Error) -> String

Render the SQLite store error carried by factos.StoreError.

Search Document