208 lines
5.5 KiB
Protocol Buffer
208 lines
5.5 KiB
Protocol Buffer
syntax = "proto3";
|
|
package waymaker.kv;
|
|
|
|
option go_package = "/apis/waymaker_kv";
|
|
|
|
// ============================================================
|
|
// WaymakerKvService — distributed key-value store implemented
|
|
// as a thin façade over the streams subsystem. Each KV bucket
|
|
// is backed by a stream named `kv:<bucket>`; KV revisions are
|
|
// stream sequence numbers; KV deletes are tombstones (per the
|
|
// WIRE_SPEC.md tombstone header convention).
|
|
//
|
|
// The service lives in its own proto so the wire surface is
|
|
// composable: an operator could ship a KV-only build, or layer
|
|
// KV on top of someone else's streams implementation.
|
|
// ============================================================
|
|
|
|
service WaymakerKvService {
|
|
// ----- Bucket lifecycle -------------------------------------
|
|
rpc CreateBucket (KvCreateBucketRequest) returns (KvCreateBucketResponse);
|
|
rpc DeleteBucket (KvDeleteBucketRequest) returns (KvDeleteBucketResponse);
|
|
|
|
// ----- Mutations --------------------------------------------
|
|
rpc Put (KvPutRequest) returns (KvPutResponse);
|
|
// CAS create — succeeds only when the key has never been
|
|
// written or its current value is a tombstone.
|
|
rpc Create (KvCreateRequest) returns (KvPutResponse);
|
|
// CAS update — succeeds only when `expected_revision`
|
|
// matches the server-side revision.
|
|
rpc Update (KvUpdateRequest) returns (KvPutResponse);
|
|
rpc Delete (KvDeleteRequest) returns (KvDeleteResponse);
|
|
|
|
// ----- Reads ------------------------------------------------
|
|
rpc Get (KvGetRequest) returns (KvGetResponse);
|
|
rpc Keys (KvKeysRequest) returns (KvKeysResponse);
|
|
rpc History (KvHistoryRequest) returns (KvHistoryResponse);
|
|
|
|
// ----- TTL refresh ------------------------------------------
|
|
rpc Touch (KvTouchRequest) returns (KvPutResponse);
|
|
|
|
// ----- Watch ------------------------------------------------
|
|
// Server-streamed event flow for a single bucket. When `key`
|
|
// is empty, every put/delete in the bucket fans out; when
|
|
// `key` is set, only events at that key are emitted.
|
|
rpc Watch (KvWatchRequest) returns (stream KvWatchEvent);
|
|
}
|
|
|
|
message KvCreateBucketRequest {
|
|
string bucket = 1;
|
|
uint64 max_bytes = 2; // 0 = unbounded
|
|
uint64 max_value_size = 3; // 0 = no per-value cap
|
|
// Bucket-level TTL (ms). 0 = no time-based eviction.
|
|
// Independent of per-key TTL set via Put.
|
|
uint64 max_age_ms = 4;
|
|
bool ephemeral = 5;
|
|
// Per-key revision cap. 0 (default) = unbounded — history depth
|
|
// is then bounded only by the bucket's stream-level retention
|
|
// (max_age_ms / max_bytes). When N > 0, after each successful
|
|
// write to a key, older revisions of *that key* beyond the N
|
|
// most recent are dropped via per-message pruning. Useful when
|
|
// one bucket hosts many keys with very different write rates —
|
|
// a fast-churning key won't crowd out older revisions of a
|
|
// slow-changing key. NATS JetStream's "MaxRevisions" semantic.
|
|
uint64 max_revisions = 6;
|
|
}
|
|
|
|
message KvCreateBucketResponse {
|
|
bool success = 1;
|
|
string result_code = 2; // "ok" | "already_exists" | "invalid_config" | "internal"
|
|
string message = 3;
|
|
}
|
|
|
|
message KvDeleteBucketRequest { string bucket = 1; }
|
|
message KvDeleteBucketResponse {
|
|
bool success = 1;
|
|
string result_code = 2; // "ok" | "no_such_bucket" | "internal"
|
|
string message = 3;
|
|
}
|
|
|
|
message KvPutRequest {
|
|
string bucket = 1;
|
|
string key = 2;
|
|
bytes value = 3;
|
|
uint64 ttl_ms = 4; // per-key TTL; 0 = no TTL
|
|
}
|
|
|
|
message KvCreateRequest {
|
|
string bucket = 1;
|
|
string key = 2;
|
|
bytes value = 3;
|
|
uint64 ttl_ms = 4;
|
|
}
|
|
|
|
message KvUpdateRequest {
|
|
string bucket = 1;
|
|
string key = 2;
|
|
bytes value = 3;
|
|
// The revision the caller believes is current. Server returns
|
|
// wrong_revision if mismatch.
|
|
uint64 expected_revision = 4;
|
|
uint64 ttl_ms = 5;
|
|
}
|
|
|
|
message KvPutResponse {
|
|
bool success = 1;
|
|
// "ok" | "no_such_bucket" | "wrong_revision" | "invalid_key" | "internal"
|
|
string result_code = 2;
|
|
string message = 3;
|
|
uint64 revision = 4;
|
|
}
|
|
|
|
message KvGetRequest {
|
|
string bucket = 1;
|
|
string key = 2;
|
|
}
|
|
|
|
message KvGetResponse {
|
|
bool success = 1;
|
|
string result_code = 2;
|
|
string message = 3;
|
|
optional KvEntry entry = 4;
|
|
}
|
|
|
|
message KvEntry {
|
|
bytes value = 1;
|
|
uint64 revision = 2;
|
|
int64 ts_ms = 3;
|
|
}
|
|
|
|
message KvDeleteRequest {
|
|
string bucket = 1;
|
|
string key = 2;
|
|
}
|
|
|
|
message KvDeleteResponse {
|
|
bool success = 1;
|
|
string result_code = 2;
|
|
string message = 3;
|
|
uint64 revision = 4;
|
|
}
|
|
|
|
message KvKeysRequest { string bucket = 1; }
|
|
|
|
message KvKeysResponse {
|
|
bool success = 1;
|
|
string result_code = 2;
|
|
string message = 3;
|
|
repeated KvKeyEntry entries = 4;
|
|
}
|
|
|
|
message KvKeyEntry {
|
|
string key = 1;
|
|
uint64 revision = 2;
|
|
bool deleted = 3;
|
|
}
|
|
|
|
message KvHistoryRequest {
|
|
string bucket = 1;
|
|
string key = 2;
|
|
uint64 from_revision = 3; // 0 = from beginning
|
|
uint64 limit = 4; // 0 = server default
|
|
}
|
|
|
|
message KvHistoryResponse {
|
|
bool success = 1;
|
|
string result_code = 2;
|
|
string message = 3;
|
|
repeated KvHistoryEntry entries = 4;
|
|
}
|
|
|
|
message KvHistoryEntry {
|
|
bytes value = 1;
|
|
uint64 revision = 2;
|
|
int64 ts_ms = 3;
|
|
bool deleted = 4;
|
|
}
|
|
|
|
message KvTouchRequest {
|
|
string bucket = 1;
|
|
string key = 2;
|
|
uint64 ttl_ms = 3;
|
|
}
|
|
|
|
message KvWatchRequest {
|
|
string bucket = 1;
|
|
string key = 2; // empty = whole bucket
|
|
}
|
|
|
|
message KvWatchEvent {
|
|
oneof event {
|
|
KvPutEvent put = 1;
|
|
KvDeleteEvent delete = 2;
|
|
}
|
|
}
|
|
|
|
message KvPutEvent {
|
|
string key = 1;
|
|
bytes value = 2;
|
|
uint64 revision = 3;
|
|
int64 ts_ms = 4;
|
|
}
|
|
|
|
message KvDeleteEvent {
|
|
string key = 1;
|
|
uint64 revision = 2;
|
|
int64 ts_ms = 3;
|
|
}
|