Documentation
¶
Overview ¶
Package catalog owns the EventKey declaration types and compiles them into a validated, immutable snapshot. Declarations are compile-time inputs: they are aggregated explicitly (see events.All), checked as a whole, and projected into read-only entries — there is no runtime registration.
Index ¶
- Constants
- func DerivedDomain(def *KeyDefinition) string
- func SubscriptionScope(def *KeyDefinition, params map[string]string) string
- func ValidateParams(def *KeyDefinition, params map[string]string) error
- type Capability
- type Descriptor
- type Entry
- type KeyDefinition
- type OutputContract
- type OutputMode
- type ParamDef
- type ParamType
- type ParamValue
- type ProcessFunc
- type RuntimeBinding
- type SchemaDef
- type SchemaSpec
- type Snapshot
- type StrategyRef
- type StrategyRefs
- type StrategySet
- type SubscriptionType
Constants ¶
const ( DefaultBufferSize = 100 MaxBufferSize = 1000 )
Variables ¶
This section is empty.
Functions ¶
func DerivedDomain ¶
func DerivedDomain(def *KeyDefinition) string
DerivedDomain returns the declaration's explicit Domain, or the key's first dot segment. The derived value feeds the Descriptor only — it is never written back into the compatibility view, so a declaration that said nothing keeps saying nothing in legacy JSON output.
func SubscriptionScope ¶
func SubscriptionScope(def *KeyDefinition, params map[string]string) string
SubscriptionScope returns a stable identifier scoped to (EventKey, values of the ParamDefs marked SubscriptionKey); the framework uses it to dedup preparation/cleanup gates and key per-subscription accounting. No SubscriptionKey params -> returns def.Key verbatim (legacy one-dimensional behavior).
Stability contract: same EventKey + same normalized param values -> same ID across CLI versions; changing the encoding requires a wire-format bump.
func ValidateParams ¶
func ValidateParams(def *KeyDefinition, params map[string]string) error
ValidateParams applies declared defaults into params, then rejects missing required and undeclared parameters. It is the single implementation every layer validates against, so a decision can never accept parameters the runtime host would refuse.
Types ¶
type Capability ¶
type Capability struct {
Preparation StrategyRef
BufferSize int
Workers int
SingleConsumer bool
}
Capability describes how a key's delivery is provisioned and bounded, in serializable form: which preparation strategy readies it, how deliveries are buffered, and whether a second consumer is rejected.
type Descriptor ¶
type Descriptor struct {
Key string
Domain string
DisplayName string
Description string
EventType string
SubscriptionType SubscriptionType
Params []ParamDef
Scopes []string
AuthTypes []string
RequiredConsoleEvents []string
}
Descriptor holds the declaration's display facts: everything list/schema render, nothing that executes. Domain is always resolved here even when the declaration left it empty.
type Entry ¶
type Entry struct {
// contains filtered or unexported fields
}
Entry is one compiled key: four projections composed read-only. Definition reassembles the canonical compatibility view from them, which doubles as the proof that the projection lost nothing.
func (*Entry) Binding ¶
func (e *Entry) Binding() RuntimeBinding
func (*Entry) Capability ¶
func (e *Entry) Capability() Capability
func (*Entry) Definition ¶
func (e *Entry) Definition() *KeyDefinition
Definition returns the canonical compatibility view of the declaration this entry was compiled from. Callers may mutate the returned value freely.
func (*Entry) Descriptor ¶
func (e *Entry) Descriptor() Descriptor
func (*Entry) Output ¶
func (e *Entry) Output() OutputContract
type KeyDefinition ¶
type KeyDefinition struct {
Key string `json:"key"`
DisplayName string `json:"display_name,omitempty"`
Description string `json:"description,omitempty"`
EventType string `json:"event_type"`
// Domain is optional in declarations: when empty it is derived from the
// key's first dot segment. When set it must match that segment — the
// compiler rejects a mismatch. The derived value lives on the Descriptor
// only; this field keeps whatever the declaration said (usually nothing),
// so legacy JSON output is unchanged.
Domain string `json:"domain,omitempty"`
// SubscriptionType selects which console "底账" the precheck reads.
// Empty is normalized to SubTypeEvent by Canonicalize.
SubscriptionType SubscriptionType `json:"subscription_type,omitempty"`
Params []ParamDef `json:"params,omitempty"`
Schema SchemaDef `json:"schema"`
// NormalizeParams canonicalizes param values BEFORE fingerprint compute,
// PreConsume, Match, and Process. Mutates the params map in place.
// May call OAPI; runs once per consumer at startup — the deciding layer
// runs it and hands the normalized values to the stream host, which then
// skips the hook (Options.ParamsNormalized).
//
// Use cases: resolve aliases ("me" -> real email, a name -> an ID),
// trim whitespace. On error, consume fails (no retry); caller gets the
// wrapped error.
//
// Default nil = no normalization, params pass through unchanged.
NormalizeParams func(ctx context.Context, rt processing.APIClient, params map[string]string) error `json:"-"`
// Process required when Schema.Custom is Processed output; must be nil when Native is used.
//
// Outcome convention: a non-nil result is emitted; (nil, nil) drops the
// event silently; processing.DropMalformed drops it with a malformed
// diagnostic; any other error drops it with a process-error diagnostic.
// Nothing a Process returns may fall outside the declared schema.
Process ProcessFunc `json:"-"`
// Match is a synchronous payload filter run on every received event
// BEFORE Process. Return false to drop the event without further work.
//
// Signature deliberately omits ctx/rt to physically enforce "no OAPI
// calls in Match". For filters that need a metadata fetch first, use
// Process and return nil to drop.
//
// Default nil = accept all events.
Match func(raw *model.Event, params map[string]string) bool `json:"-"`
// PreConsume runs once per (EventKey, SubscriptionID) when this consumer
// is first for that scope. Returns a cleanup function that the framework
// invokes when this consumer is the last for its scope.
//
// The cleanup's error return is honored: on nil the framework prints
// "[event] cleanup done."; on non-nil it prints a WARN with an
// idempotency note.
PreConsume func(ctx context.Context, rt processing.APIClient, params map[string]string) (cleanup func() error, err error) `json:"-"`
Scopes []string `json:"scopes,omitempty"`
// AuthTypes: whitelist of identities the EventKey accepts. Empty = no identity required.
AuthTypes []string `json:"auth_types,omitempty"`
RequiredConsoleEvents []string `json:"required_console_events,omitempty"`
BufferSize int `json:"buffer_size,omitempty"`
Workers int `json:"workers,omitempty"`
// SingleConsumer rejects a second consumer for the same SubscriptionID at
// the bus handshake. Default false = unlimited consumers (fan-out).
SingleConsumer bool `json:"single_consumer,omitempty"`
}
func Canonicalize ¶
func Canonicalize(def KeyDefinition) KeyDefinition
Canonicalize returns the normalized copy of a declaration: the defaults that used to be applied at registration time, made explicit. Projections and the compatibility view are both built from the canonical form, so round-trip checks compare against Canonicalize(input), never the raw input.
type OutputContract ¶
type OutputContract struct {
Mode OutputMode
SchemaJSON json.RawMessage
JQRootPath string
}
OutputContract is the compiled promise about a key's stdout: the fully resolved schema and the jq root consumers address fields from. Resolving at compile time means an unresolvable schema or a dangling field override is a startup failure, not a silently degraded rendering.
type OutputMode ¶
type OutputMode string
OutputMode states which side of the output contract a key lives on.
const ( // OutputNative delivers the raw V2 envelope verbatim. OutputNative OutputMode = "native" // OutputProcessed delivers what the key's processor emits — and only that. OutputProcessed OutputMode = "processed" )
type ParamDef ¶
type ParamDef struct {
Name string `json:"name"`
Type ParamType `json:"type"`
Required bool `json:"required"`
Default string `json:"default,omitempty"`
Description string `json:"description"`
Values []ParamValue `json:"values,omitempty"`
// SubscriptionKey marks this param as part of the subscription identity.
// Two consumers of the same EventKey but different values for any
// SubscriptionKey-marked param are treated as DISTINCT subscriptions:
// PreConsume runs once per (EventKey, SubscriptionID), cleanup runs once per
// (EventKey, SubscriptionID).
//
// CONTRACT: only mark a param SubscriptionKey if the EventKey's server-side
// subscribe/unsubscribe API is itself scoped to that resource. Lark keys the
// subscription record by (app, user, event_type) and overwrites it rather
// than reference-counting, so for a non-per-resource API the cleanup of one
// resource's last consumer unsubscribes the shared record and silently cuts
// off every other resource sharing that event_type.
//
// Default false = the param is a filter / formatting / metadata param
// and does not affect subscription identity.
SubscriptionKey bool `json:"subscription_key,omitempty"`
}
type ParamValue ¶
ParamValue.Desc is mandatory so AI consumers can decide which value to pick.
type ProcessFunc ¶
type RuntimeBinding ¶
type RuntimeBinding struct {
NormalizeParams func(ctx context.Context, rt processing.APIClient, params map[string]string) error
Match func(raw *model.Event, params map[string]string) bool
Process ProcessFunc
PreConsume func(ctx context.Context, rt processing.APIClient, params map[string]string) (cleanup func() error, err error)
}
RuntimeBinding carries the declaration's executable hooks. It has no JSON tags on purpose: behavior never travels through a rendering path.
type SchemaDef ¶
type SchemaDef struct {
Native *SchemaSpec `json:"native,omitempty"`
Custom *SchemaSpec `json:"custom,omitempty"`
FieldOverrides map[string]schemas.FieldMeta `json:"field_overrides,omitempty"`
}
SchemaDef: exactly one of Native or Custom must be set. Native auto-wraps the SDK type in the V2 envelope; Custom passes through verbatim.
type SchemaSpec ¶
type SchemaSpec struct {
Type reflect.Type `json:"-"`
Raw json.RawMessage `json:"raw,omitempty"`
}
SchemaSpec: exactly one of Type or Raw.
type Snapshot ¶
type Snapshot struct {
// contains filtered or unexported fields
}
Snapshot is the compiled, immutable catalog. Accessors return values or fresh copies — never pointers into the snapshot's own state.
func Compile ¶
func Compile(defs []KeyDefinition, strategies StrategySet) (*Snapshot, error)
Compile canonicalizes and validates every declaration, resolves each key's output schema, and projects the result into an immutable snapshot. It is the only way to obtain a Snapshot; invalid declarations produce an error and never a live snapshot.
func (*Snapshot) Definitions ¶
func (s *Snapshot) Definitions() []*KeyDefinition
Definitions returns the canonical compatibility view of every entry in key order. Each element is a fresh deep copy, like Entry.Definition.
func (*Snapshot) EventTypes ¶
EventTypes returns the sorted, deduplicated set of upstream event types — what a bus subscribes to the platform with.
type StrategyRef ¶
type StrategyRef string
StrategyRef is the serializable identifier of a consume preparation strategy. The catalog stores and validates references only; the executable strategies live with the consume application layer, which hands the compiler a StrategySet to check references against.
const ( // StrategyNone marks a key that needs no preparation before consuming. StrategyNone StrategyRef = "none" // StrategyLegacyPreConsume wraps a declaration's PreConsume hook: the // preparation decision is opaque until applied, exactly as the hook // contract has always behaved. StrategyLegacyPreConsume StrategyRef = "legacy_preconsume" )
type StrategyRefs ¶
type StrategyRefs []StrategyRef
StrategyRefs is the minimal StrategySet: a fixed collection of references.
func (StrategyRefs) Has ¶
func (s StrategyRefs) Has(ref StrategyRef) bool
type StrategySet ¶
type StrategySet interface {
Has(ref StrategyRef) bool
}
StrategySet is the narrow view the compiler needs: reference existence. Keeping the interface here (not in the application layer) lets the catalog validate without depending on strategy implementations.
type SubscriptionType ¶
type SubscriptionType string
SubscriptionType marks whether an EventKey is delivered via Lark event subscription or interactive callback subscription. It is a sibling of EventType (which holds the concrete Lark event_type string).
const ( // SubTypeEvent: checked against the published app_versions event_infos. SubTypeEvent SubscriptionType = "event" // SubTypeCallback: checked against application/get subscribed_callbacks. SubTypeCallback SubscriptionType = "callback" )