SQLStreams

the messaging platform that is just Postgres

You last visited on 9999-99-99 Show what's new since then

0646 — the topic handle carries the message type; a message key is a handle under it

Edit this page
Posted: 2026-09-08 · Report this thread
brandon Site Admin brandon profile Posts: 677

Superseded in part by [0653].

Amends [0619] and [0625].

Context. TopicHandle.CompactionHead[T], AlertHandle.Get, and MeasurementHandle.Get all read the head under a message key with no general form, and the type argument sat on every reading verb and every Register. Go 1.27 generic methods can return a generic type, so it can move up.

Decision. client.Topic[Message Versioned](name) *TopicHandle[Message], the type argument required on every topic handle. Everything under it inherits the type and takes none of its own: Group(name).Register(ctx, cfg, handler) (was client.Consumer; ConsumerHandle is deleted), Producer().Register(ctx, cfg) (was client.Producer), CompactionHeads(ctx) (the controller’s ListHeads, which three built-in readers need whole, so no limit and no second query), and Key(messageKey) *KeyHandle[Message] with MessageKey(), CompactionHead(ctx), and Messages(ctx, limit). Admin verbs ignore the type, so a topic holding two schema versions is two handles on the same rows. The key is the resource, not a Compaction() sub-handle: the key is a message property with two readers [0612], and lease facts land on the same handle later.

CompactionHead returns compaction.ErrCompactionHeadNotFound (VK0066, Permanent, new pkg/compaction/errors.go); only Get verbs are comma-ok. AlertHandle.Get and MeasurementHandle.Get become one-liners over Topic[Alert](alert.TopicName).Key(k) and map the error back to (nil, nil).

common.RawPayload []byte serves callers with no message type in scope, the CLI and admin-only scripts: SchemaVersion() returns 0 and the json.RawMessage marshal pair keeps the stored bytes verbatim. Producer, group, and scheduler Register refuse a version below 1 with a plain error. The CLI gains topic key get <topic> <key> and topic key messages <topic> <key> --limit. Schedules stay system-rooted on client.Scheduler(name): only Register knows a payload type, inferred from the payload argument. The handle’s type parameter is Message; the three methods returning the Message[Payload] alias spell their receiver [Payload], as ProducerInstance.GetCompactionHeadInTx does.

Consequences. Amends [0619]‘s clause “a struct is generic only when it holds Message-typed state”: a handle is generic to carry the type downward, holding none; controllers and datastores stay plain structs with [Message] on the method. Compile-time breaking on the client, JSON unchanged. The ROADMAP item “Register returns what you run” folds into this build.

Rejected: Topic().Compaction() as a mechanism sub-handle (the key stays positional, Messages is not a compaction fact, lease state would need a sibling); vulkan.Of[T](handle) (two handle types per level); a topic-rooted schedule (a redundant topic on seven of eight verbs and on every vulkan schedule command); an untyped Topic(name) beside the typed one (Go cannot overload). Deferred to ROADMAP Later beside the upcaster: a mismatched-version head read decodes silently.