Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Protobuf Codecs

Protobuf payloads are decoded from real .proto definitions. The definitions are uploaded as a versioned resource; the codec compiles them, decodes each payload into the message’s JSON view, and hands that to a JAQ program — the same bridge as the previous step.

The Proto File

Create proto/order_event.proto in your working directory, with field names matching order_record:

syntax = "proto3";

package quickstart;

message OrderEvent {
  string order_id = 1;
  string customer = 2;
  string status = 3;
  int64 amount = 4;
  int64 quantity = 5;
}

Upload It As A Resource

UPLOAD RESOURCE is a client-side statement — the CLI reads the directory from your machine and streams it to the cluster — so it cannot sit inside a transaction, and its path resolves relative to where nervix-cli runs:

BEGIN;
CREATE RESOURCE order_proto;
COMMIT;

UPLOAD RESOURCE order_proto VERSION './proto';

The client reports uploaded resource version 1. Uploads are immutable and versioned; see Versioning.

The Codec And Its Endpoint

The clause order is rigid: resource and its mandatory version, CONFIG (mandatory — file/include select and root the .proto files inside the resource), the fully-qualified MESSAGE name, then the target schema and JAQ program. VERSION 1 names the upload above; VERSION LATEST would bind the highest completed version when the statement is applied and store that number. The message’s JSON view keeps snake_case proto field names and numeric 64-bit integers, so a field-for-field message needs only the identity program '.':

BEGIN;

CREATE CODEC order_protobuf_codec
  FROM PROTOBUF
  USING RESOURCE order_proto VERSION 1
  CONFIG {'file' = 'order_event.proto', 'include' = '.'}
  MESSAGE 'quickstart.OrderEvent'
  TO SCHEMA order_record
  WITH JAQ TRANSFORMATIONS ON INGESTION '.';

CREATE RELAY proto_orders SCHEMA order_record UNBRANCHED;

CREATE ENDPOINT proto_ingress ON edge PATH '/proto-orders' TYPE HTTP;

CREATE HTTP ENDPOINT INGESTOR proto_order_source
  FROM proto_ingress MODE NO ACK
  ON QUIESCE BUFFER MAX SIZE 1MiB DECODE USING order_protobuf_codec
  TO proto_orders
    INHERIT ALL
    UNBRANCHED
    FLUSH IMMEDIATE
    ON MESSAGE ERROR LOG
  ON GENERAL ERROR LOG;

COMMIT;

Because it declares only ON INGESTION, this codec is decode-only; encoding to protobuf requires an ON EMITTING program. A DATETIME field would ride in a proto string plus ENCODE <field> AS RFC3339 on the codec (Codecs).

Send A Binary Order

Watch the relay:

nervix-cli --domain quickstart subscribe proto_watch proto_orders

protoc --encode turns protobuf text format into wire bytes, which curl posts as the raw body:

protoc --encode=quickstart.OrderEvent proto/order_event.proto <<'EOF' > order.bin
order_id: "o-6001"
customer: "acme"
status: "new"
amount: 4200
quantity: 6
EOF

curl -i -X POST http://127.0.0.1:8080/proto-orders \
  -H 'Host: orders.example.com' \
  -H 'Content-Type: application/octet-stream' \
  --data-binary @order.bin

The decoded record appears in the subscription — typed, with no JSON anywhere on the wire.

Next: extend the expression language itself in User-Defined Functions.