Liking cljdoc? Tell your friends :D

Thin-client protocol specification (v1)

This document is the interoperability contract for clients that do not embed corium-peer. The canonical service schema is corium.proto; protocol v1 is served by PeerServerService over gRPC/HTTP2.

Compatibility and authentication

Every transact/subscribe request sends protocol_version = 1. A mismatch is FAILED_PRECONDITION, never silent downgrade. Deployments use TLS and may require authorization: Bearer <token> metadata. Standard gRPC status codes are used: malformed EDN/query input is INVALID_ARGUMENT, an unknown database/entity is NOT_FOUND, budget exhaustion is INVALID_ARGUMENT, and upstream loss is UNAVAILABLE.

Composite value encoding

All protobuf bytes value fields contain one Corium composite item. Integers use unsigned LEB128 varints; signed integers use zig-zag then LEB128. Counts precede container contents. Multi-byte fixed scalars are big-endian.

TagMeaningPayload
00nilnone
10booleanone byte, 00 or 01
20longzig-zag varint
30doublesortable IEEE-754 bits, 8 bytes
40instantUnix milliseconds, zig-zag varint
50UUID16 bytes
61keywordinterned UTF-8 name
71stringinterned UTF-8 text
81byteslength varint + bytes
90entity refunsigned varint
a0/a1/a3list/vector/setcount + items
a2mappair count + alternating key/value items
a4tagged literalinterned tag + item
a5symbolinterned UTF-8 text

An interned string starts with varint 0, then byte-length and new UTF-8 bytes. This defines the next 1-based table slot. Later occurrences encode that non-zero slot directly. The table is per top-level message. Implementors can validate their codec against codec.rs tests.

Database views and calls

DbViewSpec names the database plus at most one of as_of, since, history, as_of_instant, or since_instant. No selector means current. The instant selectors carry Unix milliseconds and are resolved server-side against :db/txInstant to the last transaction committed at or before them; an instant older than the database resolves to basis 0. Query database views bind positionally to $, $2, and so on; args is a composite vector for remaining :in bindings. fuel = 0 requests the server default, otherwise the server clamps it to its configured ceiling.

Query relations/collections stream chunks whose rows decode to vectors and must be concatenated. Tuple/scalar results contain one item in one chunk. Always inspect shape; stop only after last = true. Datoms and transaction ranges use the same chunk/last rule. Transact provides read-your-writes on the serving peer before it responds.

Subscribe.from_basis_t is exclusive. The first item is a handshake, then the server backfills every t > from_basis_t without gaps and continues with live reports, index announcements, and heartbeats. The handshake's heartbeat_interval_ms (0 from older servers) is the server's heartbeat cadence; treat silence for a few multiples of it as a dead upstream and reconnect. After reconnect, send the last fully applied basis and deduplicate by transaction number.

Planned schema-migration compatibility

Protocol v1 does not expose schema plan/apply operations. Those remain administrative Catalog calls rather than PeerServerService calls. The proposed schema migration design requires a later protocol version because schema can then change while a subscription is live.

That version adds a schema basis and generation to the handshake and a resulting schema generation to tx reports. The handshake snapshot is effective at the subscriber's requested from_basis_t. Subsequent reports advance schema and data together in transaction order. A subscriber from basis 0 receives the creation-time pre-basis schema seed in the handshake. The seed is not a transaction and is never emitted by the exclusive t > from_basis_t backfill. The server rejects an older client during protocol version validation. Thus, the client cannot replay data against the wrong schema.

Thin clients that merely query through a peer server need no local schema planner: the server applies generations before it serves each database value. Clients consuming raw tx reports must apply schema datoms before other datoms from the same report. They must invalidate affected local assumptions. They must persist their last fully applied basis and schema generation together.

Conformance

The language-neutral behavioral corpus is in tests/conformance. The gRPC replay harness is conformance_grpc.rs. A client is conformant when it produces the same decoded EDN values for that corpus, honors every result shape and time view, rejects protocol mismatch, and resumes subscriptions gaplessly.

Can you improve this documentation? These fine people already did:
Casey Marshall & Claude
Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close