KurrentDB

A sans-IO KurrentDB client foundation for Gleam.

Package Version Hex Docs

gleam add kurrentdb@1

kurrentdb contains the transport-independent pieces of a KurrentDB client: connection configuration, operation request builders, response decoders, stream metadata helpers, gRPC frame handling, and protobuf codecs.

It does not open sockets itself. Runtime-specific packages such as kurrentdb_erlang perform the I/O.

Usage

Create a client value with host, port, and TLS settings.

import kurrentdb

pub fn client() -> kurrentdb.Client {
  kurrentdb.new("localhost", 2113, kurrentdb.TlsDisabled)
}

Connection strings using either kurrentdb:// or esdb:// can also be parsed. TLS is enabled by default and can be disabled with ?tls=false.

import kurrentdb

pub fn client_from_url() -> Result(kurrentdb.Client, Nil) {
  kurrentdb.from_connection_string(
    "esdb://admin:changeit@localhost:2113?tls=false",
  )
}

Events

Events use youid UUIDs for ids, so event ids are validated values rather than arbitrary strings.

import gleam/json
import kurrentdb/operation/append_to_stream
import youid/uuid

pub fn order_placed() -> append_to_stream.Event {
  append_to_stream.json_event(
    uuid: uuid.v7(),
    event_type: "OrderPlaced",
    data: json.object([
      #("order_id", json.string("order-123")),
      #("total", json.float(49.95)),
    ]),
  )
}

Binary payloads are supported with append_to_stream.binary_event.

Operations

Operation modules are under kurrentdb/operation. Each operation builds a typed HTTP gRPC request and decodes the typed response returned by a backend.

For example, appending events is split into request construction and response decoding.

import gleam/http/response
import kurrentdb
import kurrentdb/operation/append_to_stream

pub fn build_append_request(
  client: kurrentdb.Client,
  event: append_to_stream.Event,
) {
  append_to_stream.request(
    client,
    stream: "orders-123",
    events: [event],
    config: append_to_stream.configure(),
  )
}

pub fn decode_append_response(response: response.Response(BitArray)) {
  append_to_stream.response(response)
}

Most applications will use a backend package rather than calling these request and response functions directly.

Erlang Backend

Use kurrentdb_erlang on the Erlang target. It starts an OTP supervisor and runs each operation in a temporary worker.

gleam add kurrentdb_erlang@1
import gleam/hackney
import gleam/json
import gleam/option
import kurrentdb
import kurrentdb/operation/append_to_stream
import kurrentdb_erlang
import youid/uuid

pub fn append_order() {
  let client = kurrentdb.new("localhost", 2113, kurrentdb.TlsDisabled)
  let assert Ok(connection) =
    kurrentdb_erlang.start(client, hackney.configure(), option.None)

  let event =
    append_to_stream.json_event(
      uuid: uuid.v7(),
      event_type: "OrderPlaced",
      data: json.object([#("order_id", json.string("order-123"))]),
    )

  let task =
    kurrentdb_erlang.append_to_stream(
      connection,
      stream: "orders-123",
      events: [event],
      config: append_to_stream.configure(),
    )

  kurrentdb_erlang.await(task, within: 5000)
}

Stream Metadata

KurrentDB stores stream metadata in a metadata stream named $$<stream>. This package models the common metadata keys and ACL shape.

import gleam/json
import kurrentdb/stream_metadata

pub fn metadata() -> stream_metadata.StreamMetadata {
  stream_metadata.new()
  |> stream_metadata.max_count(100)
  |> stream_metadata.max_age(60)
  |> stream_metadata.custom("owner", json.string("billing"))
}

Status

This package is under active development. The core package is intentionally sans-IO so that KurrentDB operations can be reused across Erlang, JavaScript, and other future targets.

Development

gleam test

Further documentation can be found at https://hexdocs.pm/kurrentdb.

Search Document