catalog

package
v1.0.89 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: MIT Imports: 15 Imported by: 0

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

View Source
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 ParamType

type ParamType string
const (
	ParamString ParamType = "string"
	ParamEnum   ParamType = "enum"
	ParamMulti  ParamType = "multi"
	ParamBool   ParamType = "bool"
	ParamInt    ParamType = "int"
)

type ParamValue

type ParamValue struct {
	Value string `json:"value"`
	Desc  string `json:"desc"`
}

ParamValue.Desc is mandatory so AI consumers can decide which value to pick.

type ProcessFunc

type ProcessFunc = func(ctx context.Context, rt processing.APIClient, raw *model.Event, params map[string]string) (json.RawMessage, error)

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) Domains

func (s *Snapshot) Domains() []string

Domains returns the sorted, deduplicated domain set across all entries.

func (*Snapshot) Entries

func (s *Snapshot) Entries() []*Entry

Entries returns all compiled entries in key order.

func (*Snapshot) EventTypes

func (s *Snapshot) EventTypes() []string

EventTypes returns the sorted, deduplicated set of upstream event types — what a bus subscribes to the platform with.

func (*Snapshot) Keys

func (s *Snapshot) Keys() []string

Keys returns every compiled key in stable sorted order.

func (*Snapshot) Len

func (s *Snapshot) Len() int

Len reports how many keys were compiled.

func (*Snapshot) Resolve

func (s *Snapshot) Resolve(key string) (*Entry, bool)

Resolve returns the compiled entry for key, with ok=false for a key the catalog does not have. Every projection (descriptor, output, capability, binding) is read off the returned entry, so facts about one key can never be paired with another key's.

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"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL