KurrentDB
A sans-IO KurrentDB client foundation for Gleam.
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.