Documentation
¶
Index ¶
- Constants
- Variables
- func CtyObjectOrEmpty(m map[string]cty.Value) cty.Value
- func ExtractBlockDependencies(block *hcl.Block, excludeAttrs ...string) []string
- func ExtractReferencesFromAttribute(attr *hcl.Attribute) []string
- func ExtractReferencesFromBlock(block *hcl.Block) []string
- func ExtractReferencesFromBody(body hcl.Body, excludeAttrs map[string]bool) []string
- func FormatFunctySource(src []byte, filename string) ([]byte, hcl.Diagnostics)
- func GetBlockHandlers() map[string]BlockHandler
- func GetEventBusFromCapsule(val cty.Value) (bus.EventBus, error)
- func GetEventBusFromExpression(config *Config, busExpr hcl.Expression) (bus.EventBus, hcl.Diagnostics)
- func GetMessageTransformFromCapsule(val cty.Value) (vbxform.MessageTransformFunc, error)
- func GetSubscriberFromCapsule(val cty.Value) (bus.Subscriber, error)
- func GetSubscriberFromExpression(config *Config, subscriberExpr hcl.Expression) (bus.Subscriber, hcl.Diagnostics)
- func GetTargetFromExpression(config *Config, targetExpr hcl.Expression) (any, hcl.Diagnostics)
- func GetWireFormatFromValue(val cty.Value) (wire.WireFormat, error)
- func IsClient(val cty.Value) error
- func IsConstantExpression(expr hcl.Expression) (cty.Value, bool)
- func IsExpressionProvided(expr hcl.Expression) bool
- func IsStrictWireFormat(name string) bool
- func IsSubscriber(val cty.Value) error
- func MakeDecodeErrorHook(config *Config, expr hcl.Expression, label string) wire.DecodeErrorHook
- func MergeAttrs(maps ...map[string]AttrMeta) map[string]AttrMeta
- func NewActionSubscriber(config *Config, expr hcl.Expression) bus.Subscriber
- func NewBaggageFilterSubscriber(filter *hclutil.BaggageFilterConfig, inner bus.Subscriber, logger *zap.Logger) bus.Subscriber
- func NewClientCapsule(client Client) cty.Value
- func NewEventBusCapsule(eventBus bus.EventBus) cty.Value
- func NewMessageTransformCapsule(transformFunc vbxform.MessageTransformFunc) cty.Value
- func NewServerCapsule(server Listener) cty.Value
- func NewSubscriberCapsule(subscriber bus.Subscriber) cty.Value
- func NewWireFormatCapsule(wf wire.WireFormat) cty.Value
- func ParseConfigFiles(sources ...any) ([]hcl.Body, hcl.Diagnostics)
- func ParseDurationFromValue(val cty.Value) (time.Duration, error)
- func ParseVinitFiles(sources ...any) ([]hcl.Body, hcl.Diagnostics)
- func ProcessVinitPlugins(sources []any, pluginPath string, logger *zap.Logger) hcl.Diagnostics
- func ReconnectMaxAttempts(def *ReconnectDefinition) int
- func RegisterAmbientProvider(name string, p AmbientProvider, opts ...RegisterOption)
- func RegisterBlockSchema(blockType string, ts TypeSchema)
- func RegisterClientType(typeName string, p ClientProcessor, opts ...RegisterOption)
- func RegisterConditionSubtype(typeName string, reg ConditionRegistration, opts ...RegisterOption)
- func RegisterConditionalTriggerType(factory ConditionalTriggerTypePlugin, opts ...RegisterOption)
- func RegisterContextSchema(name string, cs ContextSchema)
- func RegisterEditorType(typeName string, p EditorProcessor, opts ...RegisterOption)
- func RegisterFunctionPlugin(name string, getter FunctionPlugin)
- func RegisterFunctyExterns(filename string, src []byte)
- func RegisterFunctyOpenType(name string, pred func(cty.Value) error)
- func RegisterFunctyType(name string, ty cty.Type)
- func RegisterHelpTopicResolver(r HelpTopicResolver)
- func RegisterServerType(typeName string, p ServerProcessor, opts ...RegisterOption)
- func RegisterSharedBlockSchema(sample any, ts TypeSchema)
- func RegisterTransformPlugin(name string, getter FunctionPlugin)
- func RegisterTriggerType(typeName string, reg TriggerRegistration, opts ...RegisterOption)
- func RegisterWireFormatType(typeName string, p WireFormatProcessor, opts ...RegisterOption)
- func RegisteredPlugins() []string
- func Reported(err error) error
- func ResolveMeterProvider(config *Config, expr hcl.Expression) (metric.MeterProvider, hcl.Diagnostics)
- func SafeResolvePath(baseDir, path string) (string, error)
- func SendFunction(config *Config) function.Function
- func SendGoFunction(config *Config) function.Function
- func SendJSONFunction(config *Config) function.Function
- func SortAttributesByDependencies(attrs hcl.Attributes, known map[string]bool) ([]*hcl.Attribute, hcl.Diagnostics)
- func ValidateAuthConfig(ac *AuthConfig) hcl.Diagnostics
- type ActionSubscriber
- type AmbientProvider
- type Assert
- type AssertBlockHandler
- type AttrMeta
- type AuthConfig
- type BaseBusClient
- type BaseClient
- type BaseServer
- type BlockHandler
- type BlockHandlerBase
- func (b *BlockHandlerBase) FinishPreprocessing(config *Config) hcl.Diagnostics
- func (b *BlockHandlerBase) FinishProcessing(config *Config) hcl.Diagnostics
- func (b *BlockHandlerBase) GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
- func (b *BlockHandlerBase) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
- func (b *BlockHandlerBase) Preprocess(block *hcl.Block) hcl.Diagnostics
- func (b *BlockHandlerBase) Process(config *Config, block *hcl.Block) hcl.Diagnostics
- type BusBlockHandler
- func (h *BusBlockHandler) BuildEventBus(config *Config, busDef *BusDefinition, defRange *hcl.Range) hcl.Diagnostics
- func (h *BusBlockHandler) FinishPreprocessing(config *Config) hcl.Diagnostics
- func (h *BusBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
- func (h *BusBlockHandler) Preprocess(block *hcl.Block) hcl.Diagnostics
- func (h *BusBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
- func (h *BusBlockHandler) Schema() TypeSchema
- type BusClient
- type BusDefinition
- type Client
- type ClientBlockHandler
- func (h *ClientBlockHandler) GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
- func (h *ClientBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
- func (h *ClientBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
- func (h *ClientBlockHandler) Schema() TypeSchema
- type ClientDefinition
- type ClientProcessor
- type ConditionBlockHandler
- type ConditionDefinition
- type ConditionProcessor
- type ConditionRegistration
- type ConditionalTriggerTypePlugin
- type Config
- func (c *Config) ActionError(diags hcl.Diagnostics) zap.Field
- func (c *Config) ActionErrorShowsSource(diags hcl.Diagnostics) bool
- func (c *Config) CreateReconnector(def ReconnectDefinition) (*bus.AutoReconnector, hcl.Diagnostics)
- func (c *Config) EnabledFeatureNames() []string
- func (c *Config) EvalCtx() *hcl.EvalContext
- func (c *Config) ExtractUserFunctions(bodies []hcl.Body) (map[string]function.Function, []hcl.Body, hcl.Diagnostics)
- func (c *Config) FuncDoc(name string) (FuncDoc, bool)
- func (c *Config) FuncHelp(name string) (string, bool)
- func (c *Config) FuncNameCandidates(name string) []string
- func (c *Config) FuncNames() []string
- func (c *Config) FunctyTestCount() int
- func (c *Config) GetDefaultInstrumentMetrics() (InstrumentMetrics, hcl.Diagnostics)
- func (c *Config) GetDefaultMetricsRegistrar() (MetricsRegistrar, hcl.Diagnostics)
- func (c *Config) GetDefaultOtlpClient() (OtlpClient, hcl.Diagnostics)
- func (c *Config) GetFeature(name string) string
- func (c *Config) GetFunctions(userFuncs map[string]function.Function) (map[string]function.Function, hcl.Diagnostics)
- func (config *Config) GetMessageTransforms(expr hcl.Expression) (transforms []vbxform.MessageTransformFunc, diags hcl.Diagnostics)
- func (c *Config) ParseDuration(expr hcl.Expression) (time.Duration, hcl.Diagnostics)
- func (c *Config) ReconnectBackoffFunc(def *ReconnectDefinition) (func(int) time.Duration, hcl.Diagnostics)
- func (c *Config) ResolveOtlpClient(expr hcl.Expression) (OtlpClient, hcl.Diagnostics)
- func (c *Config) ResolveTracerProvider(expr hcl.Expression) (trace.TracerProvider, hcl.Diagnostics)
- func (c *Config) RunTests(goctx context.Context, filter func(name string) bool) ([]functy.TestOutcome, error)
- func (config *Config) SetSignalAction(sigName string, action hcl.Expression) hcl.Diagnostics
- func (c *Config) SourceFiles() map[string]*hcl.File
- type ConfigBuilder
- func (cb *ConfigBuilder) Build() (*Config, hcl.Diagnostics)
- func (cb *ConfigBuilder) Files() map[string]*hcl.File
- func (cb *ConfigBuilder) GetBlocks(bodies []hcl.Body) (hcl.Blocks, hcl.Diagnostics)
- func (cb *ConfigBuilder) SortBlocksByDependencies(blocks hcl.Blocks, handlers map[string]BlockHandler) (hcl.Blocks, hcl.Diagnostics)
- func (c *ConfigBuilder) WithFeature(name, value string) *ConfigBuilder
- func (c *ConfigBuilder) WithLogger(logger *zap.Logger) *ConfigBuilder
- func (c *ConfigBuilder) WithPluginPath(path string) *ConfigBuilder
- func (c *ConfigBuilder) WithSources(sources ...any) *ConfigBuilder
- func (c *ConfigBuilder) WithTesting(testing bool) *ConfigBuilder
- type ConstBlockHandler
- type Constraint
- type ConstraintKind
- type ContextField
- type ContextSchema
- type CtyValuer
- type CtyWireFormat
- type EditorDefinition
- type EditorProcessor
- type ErrorlessStartable
- type FileKind
- type FsmBlockHandler
- func (h *FsmBlockHandler) FinishPreprocessing(config *Config) hcl.Diagnostics
- func (h *FsmBlockHandler) GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
- func (h *FsmBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
- func (h *FsmBlockHandler) Preprocess(block *hcl.Block) hcl.Diagnostics
- func (h *FsmBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
- func (h *FsmBlockHandler) Schema() TypeSchema
- type FsmTopLevel
- type FuncDoc
- type FuncParam
- type FunctionPlugin
- type GitAuth
- type GitDefinition
- type GitFetch
- type HandlerServer
- type HelpTopicResolver
- type Hint
- type InstrumentMetrics
- type Listener
- type MemberMeta
- type MessageConverter
- type MessageTransformWrapper
- type MetricBlockHandler
- func (h *MetricBlockHandler) FinishPreprocessing(config *Config) hcl.Diagnostics
- func (h *MetricBlockHandler) GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
- func (h *MetricBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
- func (h *MetricBlockHandler) Preprocess(block *hcl.Block) hcl.Diagnostics
- func (h *MetricBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
- func (h *MetricBlockHandler) Schema() TypeSchema
- func (h *MetricBlockHandler) SetImplicitBackendDeps(ids []string)
- type MetricDefinition
- type MetricsRegistrar
- type NamespaceSchema
- type OtlpClient
- type PluginContext
- type PluginDefinition
- type PostStartable
- type PreStoppable
- type ReactiveExpr
- type ReconnectDefinition
- type RegisterOption
- type SchemaAttr
- type SchemaBlock
- type SchemaBody
- type SchemaContext
- type SchemaContextField
- type SchemaDocument
- type SchemaGenOptions
- type SchemaMember
- type SchemaNamespace
- type SchemaNestedBlock
- type SchemaProvider
- type ServerBlockHandler
- type ServerDefinition
- type ServerProcessor
- type SignalActionHandler
- type SignalsDefinition
- type Startable
- type Stoppable
- type SubscriberSource
- type SubscriptionBlockHandler
- func (h *SubscriptionBlockHandler) GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
- func (h *SubscriptionBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
- func (h *SubscriptionBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
- func (h *SubscriptionBlockHandler) Schema() TypeSchema
- type SubscriptionDefinition
- type TLSConfig
- type TriggerBlockHandler
- func (h *TriggerBlockHandler) FinishPreprocessing(config *Config) hcl.Diagnostics
- func (h *TriggerBlockHandler) GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
- func (h *TriggerBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
- func (h *TriggerBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
- func (h *TriggerBlockHandler) Schema() TypeSchema
- type TriggerDefinition
- type TriggerProcessor
- type TriggerRegistration
- type TypeSchema
- type VariableBlockHandler
- func (h *VariableBlockHandler) FinishPreprocessing(config *Config) hcl.Diagnostics
- func (h *VariableBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
- func (h *VariableBlockHandler) Preprocess(block *hcl.Block) hcl.Diagnostics
- func (h *VariableBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
- func (h *VariableBlockHandler) Schema() TypeSchema
- type VinculumPluginInitFunc
- type WireFormatBlockHandler
- type WireFormatDefinition
- type WireFormatProcessor
Constants ¶
const ( // NamespaceProvider is a namespace contributed by an ambient provider; its // members are part of the language. NamespaceProvider = "provider" // NamespaceBlock is a namespace the config author fills in by declaring // blocks; its members are the names in that config. NamespaceBlock = "block" )
Namespace kinds, emitted as a namespace's `kind`.
const ( // CtxTypeDynamic is a value whose type depends on the data, e.g. a // decoded message payload. CtxTypeDynamic = "dynamic" // CtxTypeObject is a value with named attributes of its own. CtxTypeObject = "object" // CtxTypeCapsule is an opaque handle, passed to a function rather than // read directly. CtxTypeCapsule = "capsule" )
Context field types beyond the attribute vocabulary.
const DefaultBytesContentType = "application/octet-stream"
DefaultBytesContentType labels bytes values produced by a wire format that decoded an opaque payload. The wire formats carry no content-type information, so the generic binary type is the honest answer.
const SchemaFormatVersion = "1"
SchemaFormatVersion is the version of the `vinculum schema` output *format* (the shape of the emitted JSON document), independent of the Vinculum version that produced it. Bumped on any breaking structural change.
Variables ¶
var ( // DisabledAttr documents `disabled`. DisabledAttr = AttrMeta{ Summary: "Skip this block entirely.", Doc: "The block is parsed and validated, but nothing is created from it. " + "A block that would publish a name — `condition.<name>`, `client.<name>` — does not, " + "so any expression reading that name fails to resolve. Disable the blocks that read it too, " + "or drop the reference.", Hint: HintBool, } // TracingAttr documents `tracing`, which selects a tracing backend. TracingAttr = AttrMeta{ Summary: "Where to report traces.", Doc: "A `client \"otlp\"` block. Auto-wires to the default tracing backend when omitted.", Hint: HintTracingRef, } // MetricsAttr documents `metrics`, which selects a metrics backend. MetricsAttr = AttrMeta{ Summary: "Where to report metrics.", Doc: "A `server \"metrics\"` or `client \"otlp\"` block. Auto-wires to the default metrics backend when omitted.", Hint: HintMetricsRef, } // WireFormatAttr documents `wire_format`, which selects how message // payloads are encoded and decoded on the wire. WireFormatAttr = AttrMeta{ Summary: "How to encode and decode message payloads.", Doc: "A `wire_format` block, or the name of a built-in format. Under `auto`, " + "strings and bytes pass through and everything else is JSON-encoded; " + "decoding auto-detects JSON and falls back to a string.", Hint: HintExpression, Default: "auto", } // OnConnectAttr documents `on_connect`, which every client with a // meaningful connection lifecycle accepts. OnConnectAttr = AttrMeta{ Summary: "Evaluated after the connection is established and ready.", Doc: "Runs synchronously: no messages are produced or consumed until it returns. There is no message in flight, so no message variables are in scope.", Hint: HintActionExpression, Context: "connection", } // OnDisconnectAttr documents `on_disconnect`, the counterpart to // OnConnectAttr. OnDisconnectAttr = AttrMeta{ Summary: "Evaluated when the connection is lost or closed.", Doc: "Always runs before any reconnection attempt, and on a graceful shutdown before the connection is torn down. Every `on_connect` after the first is preceded by one.", Hint: HintActionExpression, Context: "connection", } // OnDecodeErrorAttr documents `on_decode_error`, which receivers accept to // handle a payload their wire format cannot decode. OnDecodeErrorAttr = AttrMeta{ Summary: "Evaluated when an inbound message cannot be decoded.", Doc: "The message is dropped rather than delivered. Use this to publish to a dead-letter destination or record the failure.", Hint: HintActionExpression, Context: "decode-error", } )
Attribute metadata for attributes that recur across many blocks with identical meaning. Curating them once keeps the wording consistent and keeps each block's own schema to what is actually specific to it. Blocks fold them in with MergeAttrs.
var AddTopicPrefixTransform = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "prefix", Type: cty.String}, }, Type: function.StaticReturnType(MessageTransformCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { capsule := NewMessageTransformCapsule(vbxform.AddTopicPrefix(args[0].AsString())) return capsule, nil }, })
var ChainTransformsTransform = function.New(&function.Spec{ Params: []function.Parameter{}, VarParam: &function.Parameter{ Name: "transforms", Type: cty.List(MessageTransformCapsuleType), }, Type: function.StaticReturnType(MessageTransformCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { var transforms []vbxform.MessageTransformFunc for _, arg := range args { transform, err := GetMessageTransformFromCapsule(arg) if err != nil { return cty.NullVal(retType), err } transforms = append(transforms, transform) } capsule := NewMessageTransformCapsule(vbxform.ChainTransforms(transforms...)) return capsule, nil }, })
var ClientCapsuleType = cty.CapsuleWithOps("client", reflect.TypeOf((*any)(nil)).Elem(), &cty.CapsuleOps{ GoString: func(val interface{}) string { return fmt.Sprintf("client(%p)", val) }, TypeGoString: func(_ reflect.Type) string { return "client" }, })
ClientCapsuleType is a cty capsule type for wrapping Client instances.
var Cty2GoTransform = vbxform.ModifyPayload(cty2goSimpleTransform)
Cty2GoTransform converts cty values to native Go types in message payloads.
var Cty2GoTransformFunc = function.New(&function.Spec{ Params: []function.Parameter{}, Type: function.StaticReturnType(MessageTransformCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { return NewMessageTransformCapsule(Cty2GoTransform), nil }, })
var DiffTransform = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "oldKey", Type: cty.String}, {Name: "newKey", Type: cty.String}, }, Type: function.StaticReturnType(MessageTransformCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { capsule := NewMessageTransformCapsule(vbxform.ModifyPayload(vbxform.DiffTransform(args[0].AsString(), args[1].AsString()))) return capsule, nil }, })
var DropTopicPatternTransform = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "pattern", Type: cty.String}, }, Type: function.StaticReturnType(MessageTransformCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { capsule := NewMessageTransformCapsule(vbxform.DropTopicPattern(args[0].AsString())) return capsule, nil }, })
var DropTopicPrefixTransform = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "prefix", Type: cty.String}, }, Type: function.StaticReturnType(MessageTransformCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { capsule := NewMessageTransformCapsule(vbxform.DropTopicPrefix(args[0].AsString())) return capsule, nil }, })
var EditorParamAttrs = map[string]AttrMeta{
"params": {
Summary: "Names of the parameters the compiled function takes.",
Doc: "Written as bare identifiers, e.g. `params = [host, port]`. They come after the target argument: `params = [a, b]` yields `name(ctx, target, a, b)`. Each is in scope in every expression in the block.",
},
"variadic_param": {
Summary: "Name for a parameter collecting any extra arguments.",
Doc: "A bare identifier. Arguments beyond the declared `params` are gathered into it as a list.",
},
}
EditorParamAttrs documents the parameter-naming attributes every editor block accepts, whatever its type. They are spliced into each variant.
var EventBusCapsuleType = cty.CapsuleWithOps("eventbus", reflect.TypeOf((*any)(nil)).Elem(), &cty.CapsuleOps{ GoString: func(val interface{}) string { return fmt.Sprintf("eventbus(%p)", val) }, TypeGoString: func(_ reflect.Type) string { return "eventbus" }, })
EventBusCapsuleType is a cty capsule type for wrapping EventBus instances
var IfElsePatternTransform = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "pattern", Type: cty.String}, {Name: "ifTransform", Type: MessageTransformCapsuleType}, {Name: "elseTransform", Type: MessageTransformCapsuleType}, }, Type: function.StaticReturnType(MessageTransformCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { ifTransform, err := GetMessageTransformFromCapsule(args[1]) if err != nil { return cty.NullVal(retType), err } elseTransform, err := GetMessageTransformFromCapsule(args[2]) if err != nil { return cty.NullVal(retType), err } capsule := NewMessageTransformCapsule(vbxform.IfElsePattern(args[0].AsString(), ifTransform, elseTransform)) return capsule, nil }, })
var IfElsePrefixTransform = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "prefix", Type: cty.String}, {Name: "ifTransform", Type: MessageTransformCapsuleType}, {Name: "elseTransform", Type: MessageTransformCapsuleType}, }, Type: function.StaticReturnType(MessageTransformCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { ifTransform, err := GetMessageTransformFromCapsule(args[1]) if err != nil { return cty.NullVal(retType), err } elseTransform, err := GetMessageTransformFromCapsule(args[2]) if err != nil { return cty.NullVal(retType), err } capsule := NewMessageTransformCapsule(vbxform.IfElsePrefix(args[0].AsString(), ifTransform, elseTransform)) return capsule, nil }, })
var IfPatternTransform = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "pattern", Type: cty.String}, {Name: "transform", Type: MessageTransformCapsuleType}, }, Type: function.StaticReturnType(MessageTransformCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { transformFunc, err := GetMessageTransformFromCapsule(args[1]) if err != nil { return cty.NullVal(retType), err } capsule := NewMessageTransformCapsule(vbxform.IfPattern(args[0].AsString(), transformFunc)) return capsule, nil }, })
var IfPrefixTransform = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "prefix", Type: cty.String}, {Name: "transform", Type: MessageTransformCapsuleType}, }, Type: function.StaticReturnType(MessageTransformCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { transformFunc, err := GetMessageTransformFromCapsule(args[1]) if err != nil { return cty.NullVal(retType), err } capsule := NewMessageTransformCapsule(vbxform.IfPrefix(args[0].AsString(), transformFunc)) return capsule, nil }, })
var MessageTransformCapsuleType = cty.CapsuleWithOps("transform", reflect.TypeOf((*MessageTransformWrapper)(nil)).Elem(), &cty.CapsuleOps{ GoString: func(val interface{}) string { return fmt.Sprintf("transform(%p)", val) }, TypeGoString: func(_ reflect.Type) string { return "MessageTransform" }, })
MessageTransformCapsuleType is a cty capsule type for wrapping MessageTransformFunc instances
var ReconnectAttrs = map[string]AttrMeta{ "initial_delay": { Summary: "Wait before the first retry.", Doc: "Must be greater than zero: every later wait is this one multiplied by " + "`backoff_factor`, so a zero here stays zero however many times it is " + "multiplied, and the client retries continuously.", Hint: HintDuration, Default: durationDefault(defaultReconnectInitialDelay), }, "max_delay": { Summary: "Ceiling on the wait between retries.", Hint: HintDuration, Default: durationDefault(defaultReconnectMaxDelay), }, "backoff_factor": { Summary: "Multiplier applied to the wait after each failed attempt.", Doc: "Must be at least 1. Use `1` for a constant delay between retries; a " + "factor below 1 would shorten the wait after every failure rather than " + "lengthen it, reaching zero and retrying continuously, so it is rejected.", Default: floatDefault(defaultReconnectBackoffFactor), }, "max_retries": { Summary: "Give up after this many attempts.", Doc: "Retries forever when omitted, and also when set to zero or a " + "negative number. Counts attempts to recover a *lost* connection; the " + "initial connection is retried regardless. Giving up is quiet and " + "final — the client logs an error and stays down, and the process keeps " + "running.", }, }
ReconnectAttrs documents the shared `reconnect` block. Exported so a host can layer over it with MergeAttrs rather than restating the descriptions, though no host needs to: one block means one schedule on every client, so there is nothing to specialize.
The stated defaults are the constants above rather than literals repeating them. A wrong default is worse than none, since `vinculum man` and the generated pages present it as fact, and two copies of a number are one edit away from disagreeing.
var ReplaceInTopicTransform = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "old", Type: cty.String}, {Name: "new", Type: cty.String}, }, Type: function.StaticReturnType(MessageTransformCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { capsule := NewMessageTransformCapsule(vbxform.ReplaceInTopic(args[0].AsString(), args[1].AsString())) return capsule, nil }, })
var ServerCapsuleType = cty.CapsuleWithOps("server", reflect.TypeOf((*any)(nil)).Elem(), &cty.CapsuleOps{ GoString: func(val interface{}) string { return fmt.Sprintf("server(%p)", val) }, TypeGoString: func(_ reflect.Type) string { return "server" }, })
ServerCapsuleType is a cty capsule type for wrapping Server instances
var StopTransforms = function.New(&function.Spec{ Params: []function.Parameter{}, Type: function.StaticReturnType(MessageTransformCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { capsule := NewMessageTransformCapsule(vbxform.StopTransforms()) return capsule, nil }, })
var SubscriberCapsuleType = cty.CapsuleWithOps("subscriber", reflect.TypeOf((*any)(nil)).Elem(), &cty.CapsuleOps{ GoString: func(val interface{}) string { return fmt.Sprintf("subscriber(%p)", val) }, TypeGoString: func(_ reflect.Type) string { return "subscriber" }, })
Subscriber is a cty capsule type for wrapping Susbcriber instances
var SubscriberSourceAttrs = map[string]AttrMeta{ "subscriber": { Summary: "Subscriber to forward messages to, instead of evaluating an action.", Doc: "Anything that can receive messages: a bus, an FSM, a subscriber-implementing server or client.", Hint: HintSubscriberRef, }, "action": { Summary: "Expression evaluated once per message.", Doc: "`ctx.topic` is the message topic and `ctx.msg` the payload; a protocol that extracts metadata also provides `ctx.fields`.", Hint: HintActionExpression, Context: "message", }, "transforms": { Summary: "Transform pipeline applied before the action or subscriber.", Doc: "A list of transform functions applied in order to each message. Only transform functions are in scope here.", Hint: HintTransformPipeline, }, "queue_size": { Summary: "Depth of an async queue wrapping the subscriber.", Doc: "When set, decouples delivery from the action so a slow action does not block the source.", }, }
SubscriberSourceAttrs documents the four attributes of a SubscriberSource, for every block that accepts the pattern — the subscription block and every client receiver. Fold it into a block's own attributes with MergeAttrs, and pair it with SubscriberSourceConstraints.
The `action` entry names no ctx shape, because that genuinely differs per block: a receiver's action sees the fields its protocol extracted. Override that one entry where the shape is known.
var SubscriberSourceConstraints = []Constraint{ MutuallyExclusive("action", "subscriber"), AtLeastOneOf("action", "subscriber"). WithMessage("Specify either an action to evaluate or a subscriber to forward to."), }
SubscriberSourceConstraints states the rule Resolve enforces: exactly one of subscriber or action.
var VinitDisabledAttr = AttrMeta{ Summary: "Skip this block entirely.", Doc: "Nothing the block would do at startup happens. It is evaluated against the `.vinit` " + "context, where an environment variable that is not set is not an attribute of `env` " + "at all — so gate on an optional one through `try`, as " + "`disabled = try(env.SKIP_BOOTSTRAP, \"\") != \"\"`, rather than reading it directly " + "and failing when it is absent.", Hint: HintBool, }
VinitDisabledAttr documents `disabled` on a .vinit block. DisabledAttr is written in .vcl terms — a disabled block publishing no name for expressions to read — and none of that is true here: nothing in a .vinit file publishes a name, and what a disabled block skips is a side effect at startup.
var WireFormatCapsuleType = cty.CapsuleWithOps("wire_format", reflect.TypeOf(wireFormatHolder{}), &cty.CapsuleOps{ GoString: func(val interface{}) string { h := val.(*wireFormatHolder) return fmt.Sprintf("wire_format(%s)", h.WireFormat.Name()) }, TypeGoString: func(_ reflect.Type) string { return "wire_format" }, })
WireFormatCapsuleType is the cty capsule type for wire.WireFormat values. Used to pass wire formats as cty values in VCL expressions (e.g. wire_format.myproto).
Functions ¶
func CtyObjectOrEmpty ¶ added in v0.19.0
CtyObjectOrEmpty returns cty.ObjectVal(m) when m is non-empty, or cty.EmptyObjectVal when m has no entries (cty.ObjectVal panics on empty maps).
func ExtractBlockDependencies ¶ added in v0.12.0
ExtractBlockDependencies extracts config-time variable references from a block, excluding the named runtime-only attributes at all levels.
func ExtractReferencesFromBody ¶
ExtractReferencesFromBody extracts all variable references from an HCL body, excluding attributes listed in excludeAttrs. The exclusion applies at all levels (top-level and nested blocks). Returns nil for non-hclsyntax bodies.
func FormatFunctySource ¶ added in v0.45.0
func FormatFunctySource(src []byte, filename string) ([]byte, hcl.Diagnostics)
FormatFunctySource canonically formats functy (.cty) source, using a parser configured with Vinculum's registered named types and externs so type annotations referencing host types (ctx, time, bus, …) resolve. On any parse error it returns src unchanged together with the diagnostics — functy's invariant that a file which does not fully parse is never reformatted.
func GetBlockHandlers ¶
func GetBlockHandlers() map[string]BlockHandler
func GetEventBusFromCapsule ¶
GetEventBusFromCapsule extracts an EventBus from a cty capsule value
func GetEventBusFromExpression ¶
func GetEventBusFromExpression(config *Config, busExpr hcl.Expression) (bus.EventBus, hcl.Diagnostics)
func GetMessageTransformFromCapsule ¶
func GetMessageTransformFromCapsule(val cty.Value) (vbxform.MessageTransformFunc, error)
GetMessageTransformFromCapsule extracts a MessageTransformFunc from a cty capsule value
func GetSubscriberFromCapsule ¶
func GetSubscriberFromCapsule(val cty.Value) (bus.Subscriber, error)
GetSubscriberFromCapsule extracts a Subscriber from a cty capsule value. Any capsule whose encapsulated value implements bus.Subscriber can be used (buses, clients, FSM instances, subscriber capsules, etc.).
func GetSubscriberFromExpression ¶
func GetSubscriberFromExpression(config *Config, subscriberExpr hcl.Expression) (bus.Subscriber, hcl.Diagnostics)
func GetTargetFromExpression ¶ added in v0.10.0
func GetTargetFromExpression(config *Config, targetExpr hcl.Expression) (any, hcl.Diagnostics)
func GetWireFormatFromValue ¶ added in v0.30.0
func GetWireFormatFromValue(val cty.Value) (wire.WireFormat, error)
GetWireFormatFromValue extracts a wire.WireFormat from a cty value. The value can be:
- A string naming a built-in wire format (resolved via wire.ByName)
- A capsule wrapping a wire.WireFormat
func IsClient ¶ added in v0.43.0
IsClient reports whether val is (or carries under a _capsule attribute) a capsule whose encapsulated value implements Client. It backs the functy "client" open type, matching the generic client capsule, client-specific capsules (http_client/sql_client), and rich client objects (e.g. the sql client object) alike. Null is handled by the constraint before the predicate runs.
func IsConstantExpression ¶
func IsConstantExpression(expr hcl.Expression) (cty.Value, bool)
IsConstantExpression checks if an expression is a constant (evaluatable with nil context). Returns the value and true if constant, or cty.NilVal and false otherwise.
func IsExpressionProvided ¶
func IsExpressionProvided(expr hcl.Expression) bool
IsExpressionProvided checks if an HCL expression was actually provided in the configuration. HCL creates empty expression objects for optional fields that aren't specified, but empty expressions have Start.Byte == End.Byte (zero-length range). Real expressions have End.Byte > Start.Byte (non-zero length range).
func IsStrictWireFormat ¶ added in v0.44.0
IsStrictWireFormat reports whether a decode failure is possible for the named wire format — that is, whether the format is anything other than one of the always-succeeds built-ins.
It is a heuristic used only for config-time warnings. Custom formats registered via a `wire_format` block or a plugin are treated as strict, which is the safe direction: it warns rather than staying silent.
func IsSubscriber ¶ added in v0.43.0
IsSubscriber reports whether val is a capsule whose encapsulated value implements bus.Subscriber (a bus, client, FSM, subscriber capsule, etc.). It returns nil when so, else the error from GetSubscriberFromCapsule. It backs the functy "subscriber" open type (RegisterOpenType), naming any such value in a .cty annotation while passing it through untouched. Null is handled by the constraint before the predicate runs.
func MakeDecodeErrorHook ¶ added in v0.44.0
func MakeDecodeErrorHook(config *Config, expr hcl.Expression, label string) wire.DecodeErrorHook
MakeDecodeErrorHook builds the runtime hook for a receiver's on_decode_error expression, or returns nil when the attribute is absent. A nil return tells the receiver there is no observer to invoke.
The hook is an observer only. Whatever it does — including failing to evaluate — the receiver still treats the message as failed, so every error here is logged to UserLogger and swallowed. label identifies the receiver in those log messages (e.g. `rabbitmq receiver "in"`).
The eval context follows the usual convention that ctx is the only top-level variable:
ctx.raw the undecoded body, as a bytes object ctx.error the deserialize error message ctx.wire_format the configured format name ctx.topic best-effort vinculum topic ctx.fields fields extracted before the failure ctx.<attr> per-client identity fields (routing_key, offset, ...)
func MergeAttrs ¶ added in v0.45.0
MergeAttrs combines attribute metadata maps into a new one, with later maps winning on conflict. Use it to fold shared attributes into a block's own:
Attrs: cfg.MergeAttrs(cfg.SubscriberSourceAttrs, map[string]cfg.AttrMeta{…})
func NewActionSubscriber ¶ added in v0.19.0
func NewActionSubscriber(config *Config, expr hcl.Expression) bus.Subscriber
NewActionSubscriber creates an ActionSubscriber for use by plugin sub-packages.
func NewBaggageFilterSubscriber ¶ added in v0.42.0
func NewBaggageFilterSubscriber(filter *hclutil.BaggageFilterConfig, inner bus.Subscriber, logger *zap.Logger) bus.Subscriber
NewBaggageFilterSubscriber wraps inner so that each delivered event's context has its baggage filtered per filter. A nil filter applies the secure default (strip all inbound baggage), so this should be installed unconditionally on external inbound consumers.
func NewClientCapsule ¶ added in v0.10.0
NewClientCapsule creates a new cty capsule value wrapping a Client.
func NewEventBusCapsule ¶
NewEventBusCapsule creates a new cty capsule value wrapping an EventBus
func NewMessageTransformCapsule ¶
func NewMessageTransformCapsule(transformFunc vbxform.MessageTransformFunc) cty.Value
NewMessageTransformCapsule creates a new cty capsule value wrapping a MessageTransformFunc
func NewServerCapsule ¶
NewEventBusCapsule creates a new cty capsule value wrapping an EventBus
func NewSubscriberCapsule ¶
func NewSubscriberCapsule(subscriber bus.Subscriber) cty.Value
NewSubscriberCapsule creates a new cty capsule value wrapping an Subscriber
func NewWireFormatCapsule ¶ added in v0.30.0
func NewWireFormatCapsule(wf wire.WireFormat) cty.Value
NewWireFormatCapsule wraps a wire.WireFormat in a cty capsule value.
func ParseConfigFiles ¶
func ParseConfigFiles(sources ...any) ([]hcl.Body, hcl.Diagnostics)
func ParseDurationFromValue ¶ added in v0.19.0
ParseDurationFromValue converts an already-evaluated cty.Value to a time.Duration. Supports numbers (seconds), strings (Go or ISO 8601), and duration capsules. Used when the expression must be evaluated against a dynamic context before conversion.
func ParseVinitFiles ¶ added in v0.37.0
func ParseVinitFiles(sources ...any) ([]hcl.Body, hcl.Diagnostics)
ParseVinitFiles enumerates *.vinit files from directory and embed.FS sources, plus any string source whose path ends in ".vinit". Byte-slice and []string sources are ignored — vinit content is always discovered from files on disk (or an embedded FS), never from in-memory bytes.
func ProcessVinitPlugins ¶ added in v0.45.0
ProcessVinitPlugins runs only the plugin-loading portion of the .vinit pass, deliberately skipping `git` blocks (which clone and materialize repos — a side effect no read-only tool should trigger). Tooling such as `fmt` calls it so plugin-registered contributions (e.g. functy types via RegisterFunctyType) are available when parsing/formatting, without the cost of a full Build.
func ReconnectMaxAttempts ¶ added in v0.45.0
func ReconnectMaxAttempts(def *ReconnectDefinition) int
ReconnectMaxAttempts is max_retries as a client library's max-attempts field wants it: the number of attempts to allow, where zero or negative means unlimited. Zero is unlimited rather than "do not reconnect" because that is what bus.AutoReconnector has always meant by it (`maxRetries > 0 && ...`), and because it makes an omitted attribute mean what it meant before the attribute was honored at all.
A companion to ReconnectBackoffFunc rather than part of it: a backoff function answers "how long until the next attempt", and stopping is not an answer to that question. Clients pass both.
func RegisterAmbientProvider ¶ added in v0.19.0
func RegisterAmbientProvider(name string, p AmbientProvider, opts ...RegisterOption)
RegisterAmbientProvider registers a named provider that contributes a top-level value to the HCL evaluation context. Sub-packages call this from init().
Pass WithNamespaceSchema to describe what the value carries. A provider registered without one still appears in `vinculum schema`, flagged "undocumented", so the gap is visible rather than invisible.
func RegisterBlockSchema ¶ added in v0.45.0
func RegisterBlockSchema(blockType string, ts TypeSchema)
RegisterBlockSchema records the schema of a top-level block that has no BlockHandler to carry it — the blocks extracted early in Build() such as `function` and `jq`. Blocks with a handler implement SchemaProvider instead.
func RegisterClientType ¶ added in v0.19.0
func RegisterClientType(typeName string, p ClientProcessor, opts ...RegisterOption)
RegisterClientType registers a processor for a named client type. Sub-packages call this from their init() function, optionally passing WithSchema to describe the block for `vinculum schema`.
func RegisterConditionSubtype ¶ added in v0.27.0
func RegisterConditionSubtype(typeName string, reg ConditionRegistration, opts ...RegisterOption)
RegisterConditionSubtype registers a condition subtype ("timer", "threshold", "counter"). Sub-packages call this from init(), optionally passing WithSchema to describe the block for `vinculum schema`.
func RegisterConditionalTriggerType ¶ added in v0.21.0
func RegisterConditionalTriggerType(factory ConditionalTriggerTypePlugin, opts ...RegisterOption)
RegisterConditionalTriggerType registers a trigger type whose availability depends on config state (e.g. a feature flag). Unlike RegisterTriggerType, it does NOT call recordPlugin at init time; the plugin name is recorded only when the factory returns a non-nil result during Build().
The factory cannot be invoked without a *Config, so it cannot reveal its type names for `vinculum schema`. Pass WithVariantSchemas to name and describe them; they are emitted as the full superset, flagged conditional.
func RegisterContextSchema ¶ added in v0.45.0
func RegisterContextSchema(name string, cs ContextSchema)
RegisterContextSchema describes the `ctx` shape that AttrMeta.Context names. Call it from an init() in the package that builds the context.
func RegisterEditorType ¶ added in v0.23.0
func RegisterEditorType(typeName string, p EditorProcessor, opts ...RegisterOption)
RegisterEditorType registers an editor type. Sub-packages call this from init(), optionally passing WithSchema to describe the block for `vinculum schema`.
func RegisterFunctionPlugin ¶ added in v0.19.0
func RegisterFunctionPlugin(name string, getter FunctionPlugin)
RegisterFunctionPlugin registers a named function plugin. Sub-packages call this from their init() function.
func RegisterFunctyExterns ¶ added in v0.43.0
RegisterFunctyExterns registers a //functy:extern source declaring the *real* signatures of functions a package contributes as a function plugin. Call it from the same init() that registers the plugin, so the declarations sit next to the functions they describe.
It exists because a cty function's own metadata often cannot describe it. cty can only make a *trailing* parameter optional, so a function taking an optional leading context — the whole rich-cty-types get/set/count family — has to fake it with a variadic, and reflects uselessly as `get(thing, ...args)`. An extern states what the function actually accepts, so help() and editor tooling can show it.
The source must carry the //functy:extern directive itself. It is not compiled and declares nothing callable; it only documents functions the host already provides. Note that functy checks extern names for collisions, which the function-plugin registry does not: two packages declaring an extern for the same name is an error, as is an extern that collides with a user's .cty function.
cfg.RegisterFunctionPlugin("generic", func(*cfg.Config) map[string]function.Function {
return richcty.GetGenericFunctions()
})
cfg.RegisterFunctyExterns(richcty.ExternsFilename, richcty.Externs())
func RegisterFunctyOpenType ¶ added in v0.43.0
RegisterFunctyOpenType registers an open, predicate-backed named type: the value is passed through untouched when pred returns nil (attributes preserved), else rejected. Use only when no single fixed cty.Type exists — a rich object whose attribute set varies per instance, or a heterogeneous interface-dispatch type spanning many capsule types.
func RegisterFunctyType ¶ added in v0.43.0
RegisterFunctyType registers a closed (identity-enforced) named type for use in .cty type annotations: a raw capsule type, or a rich object's Object type when that object has a *fixed* attribute set (a single static cty.Type). Prefer this over the open form — closed types are usable in more positions. Call from a package's init(); applied when the functy parser is built during Build().
func RegisterHelpTopicResolver ¶ added in v0.45.0
func RegisterHelpTopicResolver(r HelpTopicResolver)
RegisterHelpTopicResolver installs the resolver that help() consults for topics that are not functions. A second call replaces the first.
func RegisterServerType ¶ added in v0.19.0
func RegisterServerType(typeName string, p ServerProcessor, opts ...RegisterOption)
RegisterServerType registers a processor for a named server type. Sub-packages call this from their init() function, optionally passing WithSchema to describe the block for `vinculum schema`.
func RegisterSharedBlockSchema ¶ added in v0.45.0
func RegisterSharedBlockSchema(sample any, ts TypeSchema)
RegisterSharedBlockSchema records curated metadata for a sub-block struct used by many parent blocks (e.g. cfg.TLSConfig), so it is documented once rather than in every host. sample is a zero value of the struct, normally a pointer to one. A parent that curates the same sub-block wins over this.
func RegisterTransformPlugin ¶ added in v0.37.0
func RegisterTransformPlugin(name string, getter FunctionPlugin)
RegisterTransformPlugin registers a named getter that contributes transform-context functions. Each function in the returned map must produce a value of type MessageTransformCapsuleType.
Sub-packages (and Go plugins) call this from their init() function, or from a plugin's VinculumPluginInit. The getter is invoked when Config builds the transform-only eval context.
Names that collide with a built-in transform or with another registered transform plugin produce a fatal diagnostic at Build() time, naming the offending plugin and the conflicting function name.
func RegisterTriggerType ¶ added in v0.19.0
func RegisterTriggerType(typeName string, reg TriggerRegistration, opts ...RegisterOption)
RegisterTriggerType registers an unconditional trigger type. Sub-packages call this from their init() function, optionally passing WithSchema to describe the block for `vinculum schema`.
func RegisterWireFormatType ¶ added in v0.30.0
func RegisterWireFormatType(typeName string, p WireFormatProcessor, opts ...RegisterOption)
RegisterWireFormatType registers a processor for a named wire format type. Sub-packages call this from their init() function, optionally passing WithSchema to describe the block for `vinculum schema`.
func RegisteredPlugins ¶ added in v0.19.0
func RegisteredPlugins() []string
RegisteredPlugins returns a sorted copy of all registered plugin names, e.g. "ambient.sys", "client.kafka", "functions.stdlib", "server.mcp", "trigger.start".
func Reported ¶ added in v0.45.0
Reported marks an error as already logged, for a subscriber outside this package that renders its own failures — a client receiver's action, say. Pair it with ActionErrorShowsSource, which says whether there was anything worth rendering.
func ResolveMeterProvider ¶ added in v0.24.0
func ResolveMeterProvider(config *Config, expr hcl.Expression) (metric.MeterProvider, hcl.Diagnostics)
ResolveMeterProvider resolves a metric.MeterProvider from an optional HCL expression. If the expression is provided it must reference a server "metrics" or client "otlp" block. If omitted, the default metrics backend is used. Returns nil, nil when no metrics backend is configured (metrics disabled).
func SafeResolvePath ¶ added in v0.23.0
SafeResolvePath resolves path relative to baseDir and verifies the result is contained within baseDir, rejecting directory traversal and home directory expansion.
func SendFunction ¶
SendFunction returns a cty function for sending a message to a bus subscriber (original behavior)
func SendGoFunction ¶
SendGoFunction returns a cty function for sending a Go native type message to a bus subscriber
func SendJSONFunction ¶
SendJSONFunction returns a cty function for sending a JSON string message to a bus subscriber
func SortAttributesByDependencies ¶
func SortAttributesByDependencies(attrs hcl.Attributes, known map[string]bool) ([]*hcl.Attribute, hcl.Diagnostics)
SortAttributesByDependencies returns attribute names sorted in dependency order. known contains variable root names that are already available in the evaluation context (e.g. ambient providers like "env", "sys") and should not be treated as missing dependencies.
func ValidateAuthConfig ¶ added in v0.20.0
func ValidateAuthConfig(ac *AuthConfig) hcl.Diagnostics
ValidateAuthConfig checks that the required fields for the selected mode are present and that no conflicting options were set. Returns HCL diagnostics on error.
Types ¶
type ActionSubscriber ¶
type ActionSubscriber struct {
bus.BaseSubscriber
Config *Config
ActionExpr hcl.Expression
}
type AmbientProvider ¶ added in v0.19.0
AmbientProvider is a function that contributes a named value to the global HCL evaluation context. Providers register themselves via RegisterAmbientProvider in their init() functions; config.Build() loops over all registered providers to populate config.Constants before evaluating any blocks.
type Assert ¶
The assert block is used to assert a condition at configuration processing runtime. It is mainly intended for testing.
type AssertBlockHandler ¶
type AssertBlockHandler struct {
BlockHandlerBase
}
func NewAssertBlockHandler ¶
func NewAssertBlockHandler() *AssertBlockHandler
func (*AssertBlockHandler) GetBlockDependencyId ¶
func (h *AssertBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
func (*AssertBlockHandler) Process ¶
func (h *AssertBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
func (*AssertBlockHandler) Schema ¶ added in v0.45.0
func (h *AssertBlockHandler) Schema() TypeSchema
Schema describes the assert block for `vinculum schema`.
type AttrMeta ¶ added in v0.45.0
type AttrMeta struct {
// Summary is a one-line description, shown as a completion item's detail.
Summary string
// Doc is richer Markdown for hover.
Doc string
// Hint tells a completion provider what kind of value belongs after `=`.
Hint Hint
// Context names the shape of `ctx` this attribute's expression is
// evaluated against, for attributes evaluated at event time. The shape
// varies per *attribute*, not per block: a receiver's `action` sees
// ctx.topic/ctx.msg/ctx.fields, while `on_connect` on the same client sees
// none of them and `on_decode_error` sees the failure instead.
//
// Use a stable kebab-case name shared by every attribute with the same
// shape (e.g. "message", "http-request", "connection"), and describe the
// shape itself with RegisterContextSchema. Naming a shape that nothing
// describes — or describing one nothing names — is a reported problem.
Context string
// ContextFields are fields this attribute's `ctx` carries in addition to
// the ones its shape declares. Only an open shape — one whose OpenFields
// is set — accepts them: `on_decode_error` has the same five fixed fields
// everywhere, plus identity fields chosen by the receiver, so the mqtt
// receiver adds `mqtt_topic` where the rabbitmq one adds `routing_key`.
//
// A name that the shape already declares, or that a universal field takes,
// is a reported problem — it is exactly the collision the runtime resolves
// by dropping the site's field.
ContextFields []ContextField
// Enum is the closed set of legal string values, when there is one.
Enum []string
// Default is the value the attribute takes when it is omitted, written as
// it would be written in a config file: `30s`, `true`, `0`. A computed
// default may be written as the pattern it follows
// (`vinculum-<name>-<hostname>`).
//
// Leave it empty when there is no default worth stating — a required
// attribute has none, and neither does an optional one whose absence means
// "do nothing" rather than "do this instead". It is rendered as a literal,
// so a default that can only be explained in a sentence ("the vinculum
// topic, verbatim") belongs in Doc instead; a backticked sentence in a
// Default column reads as a value and is not one.
//
// This is curated, like Summary, because the defaults are applied
// imperatively while processing a block (`keepAlive := 30 * time.Second`)
// rather than declared anywhere reflection can reach. Prefer stating it
// here over burying it in Doc prose: a default is the second thing a reader
// wants after what the attribute means, and a consumer can only put it in
// its own column if it arrives as its own field.
Default string
// Deprecated, when non-empty, marks the attribute deprecated and explains
// the replacement.
Deprecated string
}
AttrMeta is curated metadata for a single HCL attribute.
func (AttrMeta) WithContextFields ¶ added in v0.45.0
func (meta AttrMeta) WithContextFields(fields ...ContextField) AttrMeta
WithContextFields returns a copy of meta carrying the given additional `ctx` fields. Use it to specialize a shared AttrMeta per site:
"on_decode_error": cfg.OnDecodeErrorAttr.WithContextFields(
cfg.ContextField{Name: "routing_key", Type: "string", Summary: "…"},
),
func (AttrMeta) WithDefault ¶ added in v0.45.0
WithDefault returns a copy of meta stating the given default. Use it where a shared AttrMeta describes an attribute whose default is genuinely the host's choice rather than the attribute's:
"max_delay": cfg.SomeSharedAttrs["max_delay"].WithDefault("60s"),
Reach for it sparingly. A shared attribute that means different things per host is usually a bug wearing a schema, and the fix is to make the hosts agree rather than to document that they do not.
type AuthConfig ¶ added in v0.20.0
type AuthConfig struct {
Mode string `hcl:"mode,label"` // "basic" | "oidc" | "oauth2" | "custom" | "none"
// disabled — when true the block is parsed but inert, exactly as if it were
// absent (server-level auth) or "none" (block-level). Mode-specific required
// fields are not validated. Typically driven by an env expression so a single
// var can both supply credentials and toggle auth on/off.
Disabled bool `hcl:"disabled,optional"`
// basic — realm shown in WWW-Authenticate header; defaults to server name
Realm string `hcl:"realm,optional"`
// basic — map(string) expression; username → plaintext password
Credentials hcl.Expression `hcl:"credentials,optional"`
// basic + custom — expression evaluated per request
Action hcl.Expression `hcl:"action,optional"`
// oidc + oauth2 — required aud values; token must contain at least one
Audience hcl.Expression `hcl:"audience,optional"` // list(string)
// oidc — OIDC issuer URL (used for discovery)
Issuer string `hcl:"issuer,optional"`
// oidc — override the JWKS endpoint (disables OIDC discovery)
JWKSUrl string `hcl:"jwks_url,optional"`
// oidc — permitted signing algorithms; defaults to ["RS256","ES256"]
Algorithms hcl.Expression `hcl:"algorithms,optional"` // list(string)
// oidc — permitted clock skew for exp/nbf; defaults to "30s".
// Accepts a string ("30s"), a number (seconds), or a duration capsule.
ClockSkew hcl.Expression `hcl:"clock_skew,optional"`
// oidc (introspection) + oauth2 — RFC 7662 introspection endpoint
IntrospectUrl string `hcl:"introspect_url,optional"`
// oidc introspection — client ID for introspection endpoint
IntrospectClientID string `hcl:"introspect_client_id,optional"`
// oidc introspection — client secret for introspection endpoint
IntrospectClientSecret string `hcl:"introspect_client_secret,optional"`
// oauth2 — client ID for introspection endpoint (required)
ClientID string `hcl:"client_id,optional"`
// oauth2 — client secret (required; use env.VAR)
ClientSecret string `hcl:"client_secret,optional"`
// oauth2 — cache TTL for introspection results; defaults to "0s" (no cache).
// Accepts a string ("60s"), a number (seconds), or a duration capsule.
CacheTTL hcl.Expression `hcl:"cache_ttl,optional"`
DefRange hcl.Range `hcl:",def_range"`
}
AuthConfig holds the configuration for an auth block. It is designed to be embedded (as a pointer) in any server or handler block that supports auth, decoded by gohcl.
The block label selects the authentication mode:
auth "basic" { realm = "API", credentials = { alice = "s3cr3t" } }
auth "oidc" { issuer = "https://accounts.example.com", audience = ["api.example.com"] }
auth "oauth2" { introspect_url = "...", client_id = "...", client_secret = env.SECRET }
auth "custom" { action = lookup_session(ctx.request.cookie("session")) }
auth "none" {} # explicitly opt out of inherited server-level auth
type BaseBusClient ¶ added in v0.14.0
type BaseBusClient struct {
BaseClient
Subscriber bus.Subscriber
Client bus.Client
}
BaseBusClient is the base struct for bus-backed clients (VWS, etc.).
func (*BaseBusClient) GetClient ¶ added in v0.14.0
func (s *BaseBusClient) GetClient() bus.Client
func (*BaseBusClient) GetSubscriber ¶ added in v0.14.0
func (s *BaseBusClient) GetSubscriber() bus.Subscriber
func (*BaseBusClient) SetSubscriber ¶ added in v0.14.0
func (s *BaseBusClient) SetSubscriber(subscriber bus.Subscriber)
type BaseClient ¶ added in v0.10.0
BaseClient holds the minimal fields common to all client types.
func (*BaseClient) GetDefRange ¶ added in v0.10.0
func (s *BaseClient) GetDefRange() hcl.Range
func (*BaseClient) GetName ¶ added in v0.10.0
func (s *BaseClient) GetName() string
func (*BaseClient) SetDefRange ¶ added in v0.34.0
func (s *BaseClient) SetDefRange(r hcl.Range)
type BaseServer ¶
func (*BaseServer) GetDefRange ¶
func (s *BaseServer) GetDefRange() hcl.Range
func (*BaseServer) GetName ¶
func (s *BaseServer) GetName() string
type BlockHandler ¶
type BlockHandler interface {
Preprocess(block *hcl.Block) hcl.Diagnostics
FinishPreprocessing(config *Config) hcl.Diagnostics
GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
Process(config *Config, block *hcl.Block) hcl.Diagnostics
FinishProcessing(config *Config) hcl.Diagnostics
}
type BlockHandlerBase ¶
type BlockHandlerBase struct {
}
func (*BlockHandlerBase) FinishPreprocessing ¶
func (b *BlockHandlerBase) FinishPreprocessing(config *Config) hcl.Diagnostics
func (*BlockHandlerBase) FinishProcessing ¶
func (b *BlockHandlerBase) FinishProcessing(config *Config) hcl.Diagnostics
func (*BlockHandlerBase) GetBlockDependencies ¶
func (b *BlockHandlerBase) GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
func (*BlockHandlerBase) GetBlockDependencyId ¶
func (b *BlockHandlerBase) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
func (*BlockHandlerBase) Preprocess ¶
func (b *BlockHandlerBase) Preprocess(block *hcl.Block) hcl.Diagnostics
func (*BlockHandlerBase) Process ¶
func (b *BlockHandlerBase) Process(config *Config, block *hcl.Block) hcl.Diagnostics
type BusBlockHandler ¶
type BusBlockHandler struct {
BlockHandlerBase
// contains filtered or unexported fields
}
func NewBusBlockHandler ¶
func NewBusBlockHandler() *BusBlockHandler
func (*BusBlockHandler) BuildEventBus ¶
func (h *BusBlockHandler) BuildEventBus(config *Config, busDef *BusDefinition, defRange *hcl.Range) hcl.Diagnostics
func (*BusBlockHandler) FinishPreprocessing ¶
func (h *BusBlockHandler) FinishPreprocessing(config *Config) hcl.Diagnostics
func (*BusBlockHandler) GetBlockDependencyId ¶
func (h *BusBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
func (*BusBlockHandler) Preprocess ¶
func (h *BusBlockHandler) Preprocess(block *hcl.Block) hcl.Diagnostics
func (*BusBlockHandler) Process ¶
func (h *BusBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
func (*BusBlockHandler) Schema ¶ added in v0.45.0
func (h *BusBlockHandler) Schema() TypeSchema
Schema describes the bus block for `vinculum schema`.
type BusClient ¶ added in v0.14.0
type BusClient interface {
Client
Build() (bus.Client, error)
GetClient() bus.Client
GetSubscriber() bus.Subscriber
SetSubscriber(subscriber bus.Subscriber)
}
BusClient is a client backed by the vinculum-bus pub/sub system (e.g. VWS).
type BusDefinition ¶
type BusDefinition struct {
Name string `hcl:"name,label"`
Type *string `hcl:"type,optional"`
QueueSize *int `hcl:"queue_size,optional"`
Metrics hcl.Expression `hcl:"metrics,optional"`
Tracing hcl.Expression `hcl:"tracing,optional"`
}
type Client ¶ added in v0.10.0
Client is the base identity interface for all client types.
func GetClientFromCapsule ¶ added in v0.10.0
GetClientFromCapsule extracts a Client from a cty capsule value. Any capsule whose encapsulated value implements Client is accepted (the generic client capsule, or a client-specific capsule like http_client/sql_client), mirroring GetSubscriberFromCapsule — so client-specific capsule types dispatch here too.
func GetClientFromExpression ¶ added in v0.10.0
func GetClientFromExpression(config *Config, clientExpr hcl.Expression) (Client, hcl.Diagnostics)
type ClientBlockHandler ¶ added in v0.10.0
type ClientBlockHandler struct {
BlockHandlerBase
}
func NewClientBlockHandler ¶ added in v0.10.0
func NewClientBlockHandler() *ClientBlockHandler
func (*ClientBlockHandler) GetBlockDependencies ¶ added in v0.16.0
func (h *ClientBlockHandler) GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
func (*ClientBlockHandler) GetBlockDependencyId ¶ added in v0.10.0
func (h *ClientBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
func (*ClientBlockHandler) Process ¶ added in v0.10.0
func (h *ClientBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
func (*ClientBlockHandler) Schema ¶ added in v0.45.0
func (h *ClientBlockHandler) Schema() TypeSchema
Schema describes the client block for `vinculum schema`. A typed block has no body of its own; each client type contributes its own via WithSchema.
type ClientDefinition ¶ added in v0.10.0
type ClientProcessor ¶ added in v0.19.0
type ClientProcessor func(config *Config, block *hcl.Block, body hcl.Body) (Client, hcl.Diagnostics)
ClientProcessor is a function that processes a client block and returns a Client.
type ConditionBlockHandler ¶ added in v0.27.0
type ConditionBlockHandler struct {
BlockHandlerBase
}
func NewConditionBlockHandler ¶ added in v0.27.0
func NewConditionBlockHandler() *ConditionBlockHandler
func (*ConditionBlockHandler) GetBlockDependencyId ¶ added in v0.27.0
func (h *ConditionBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
GetBlockDependencyId returns "condition.<name>" so blocks referencing the condition are ordered after it.
func (*ConditionBlockHandler) Process ¶ added in v0.27.0
func (h *ConditionBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
func (*ConditionBlockHandler) Schema ¶ added in v0.45.0
func (h *ConditionBlockHandler) Schema() TypeSchema
type ConditionDefinition ¶ added in v0.27.0
type ConditionDefinition struct {
Type string `hcl:"type,label"`
Name string `hcl:"name,label"`
Disabled bool `hcl:"disabled,optional"`
DefRange hcl.Range `hcl:",def_range"`
RemainingBody hcl.Body `hcl:",remain"`
}
ConditionDefinition is the common envelope for every condition subtype. Subtype-specific attributes live in RemainingBody and are decoded by the registered ConditionProcessor.
type ConditionProcessor ¶ added in v0.27.0
type ConditionProcessor func(config *Config, block *hcl.Block, def *ConditionDefinition) hcl.Diagnostics
ConditionProcessor processes a single condition block of a given subtype.
type ConditionRegistration ¶ added in v0.27.0
type ConditionRegistration struct {
Process ConditionProcessor
HasDependencyId bool
}
ConditionRegistration holds the processor and metadata for a condition subtype. HasDependencyId is true when the subtype publishes a cty value at condition.<name> (all current subtypes do; the flag exists for symmetry with TriggerRegistration).
type ConditionalTriggerTypePlugin ¶ added in v0.21.0
type ConditionalTriggerTypePlugin func(cfg *Config) map[string]TriggerRegistration
ConditionalTriggerTypePlugin is evaluated once per Build(). It returns a map of trigger type names to registrations when the required feature is enabled, or nil when the type should not be available for this config.
type Config ¶
type Config struct {
Logger *zap.Logger
// UserLogger is Logger with Go caller and stacktrace suppressed. Use it
// at sites that report errors caused by user-supplied VCL (expression
// eval failures, assertion failures, action errors, etc.) where the Go
// source location and stack are noise rather than signal.
UserLogger *zap.Logger
Functions map[string]function.Function
Constants map[string]cty.Value
Features map[string]string
BaseDir string
WriteDir string
// Testing is true when the config is built for `vinculum test`. It is
// projected to VCL as the `sys.testing` ambient bool, so a config can gate
// real external I/O off under test (e.g. `disabled = sys.testing`).
Testing bool
SigActions *SignalActionHandler
Startables []Startable
PostStartables []PostStartable
PreStoppables []PreStoppable
Stoppables []Stoppable
BusCapsuleType cty.Type
CtyBusMap map[string]cty.Value
Buses map[string]bus.EventBus
CtyClientMap map[string]cty.Value
Clients map[string]map[string]Client
CtyServerMap map[string]cty.Value
Servers map[string]map[string]Listener
CtyVarMap map[string]cty.Value
CtyTriggerMap map[string]cty.Value
TriggerDefRanges map[string]hcl.Range
CtyConditionMap map[string]cty.Value
CtyFsmMap map[string]cty.Value
CtyWireFormatMap map[string]cty.Value
MetricsServers map[string]MetricsRegistrar
OtlpClients map[string]OtlpClient
// contains filtered or unexported fields
}
func (*Config) ActionError ¶ added in v0.43.0
func (c *Config) ActionError(diags hcl.Diagnostics) zap.Field
ActionError renders an action/expression evaluation failure as a zap field (keyed "error", like zap.Error) for logging via UserLogger: the failing line quoted from its source, plus any assert operand detail (e.g. `n = -3`) when a functy throw carries one.
A throw is rendered against its own range rather than the call that surfaced it, which is why it is recovered first: the useful line is the `assert` in the .cty file, not the expression that called into it. Everything else is rendered where it failed, which for a VCL expression is the `action =` line.
Use it in place of zap.Error(diags) at action-evaluation error sites:
config.UserLogger.Error("... action error", zap.String("name", n), config.ActionError(diags))
func (*Config) ActionErrorShowsSource ¶ added in v0.45.0
func (c *Config) ActionErrorShowsSource(diags hcl.Diagnostics) bool
ActionErrorShowsSource reports whether ActionError would render these diagnostics against their source rather than fall back to their plain text.
It is the question a site that *also* returns the failure to a generic handler has to answer: log here only when doing so shows something that handler cannot, and leave the rest to the handler rather than say the same thing twice.
func (*Config) CreateReconnector ¶ added in v0.10.0
func (c *Config) CreateReconnector(def ReconnectDefinition) (*bus.AutoReconnector, hcl.Diagnostics)
CreateReconnector lowers a reconnect block into the bus.AutoReconnector a bus client takes. Unlike ReconnectBackoffFunc's consumers, this one is handed the whole schedule at once because the reconnector owns the retry loop itself.
Every value is set explicitly rather than left to bus.NewAutoReconnector's own defaults, so the block means the same here as it does on a protocol client. max_retries goes through ReconnectMaxAttempts for the same reason: one attribute, one normalization, whichever client is asking. The builder reads anything not greater than zero as unlimited, which is what an absent, zero, or negative max_retries resolves to.
func (*Config) EnabledFeatureNames ¶ added in v0.19.0
EnabledFeatureNames returns the names of all enabled features, sorted.
func (*Config) EvalCtx ¶ added in v0.19.0
func (c *Config) EvalCtx() *hcl.EvalContext
EvalCtx returns the HCL evaluation context for use by plugin sub-packages.
func (*Config) ExtractUserFunctions ¶
func (c *Config) ExtractUserFunctions(bodies []hcl.Body) (map[string]function.Function, []hcl.Body, hcl.Diagnostics)
ExtractUserFunctions wraps the functions package ExtractUserFunctions
func (*Config) FuncDoc ¶ added in v0.45.0
FuncDoc returns what is known about one callable function, or reports false when nothing of that name is callable.
The precedence is help()'s, and deliberately: a declaration beats the eval context, because a declaration exists precisely when the cty metadata is wrong — the get/set/count family fakes an optional *leading* ctx with a trailing variadic, and reflects as the useless `get(thing, ...args)`.
func (*Config) FuncHelp ¶ added in v0.45.0
FuncHelp renders one function's help, or reports false when nothing of that name is callable.
This is the same rendering `help("name")` returns from inside an expression, because it is the same call: `vinculum man --type function send` and `help("send")` cannot describe a function differently.
func (*Config) FuncNameCandidates ¶ added in v0.45.0
FuncNameCandidates returns the qualified names a bare name could have meant, when it could have meant more than one.
A name that resolves, and a name that names nothing, both return nothing: this answers only the third case, which is otherwise indistinguishable from the second. Without it, `help("dup")` across two namespaces reports "no such function" for a function that exists twice.
func (*Config) FuncNames ¶ added in v0.45.0
FuncNames returns the names of every function callable in this Config's assembled eval context, sorted.
Private functy functions are absent — they were never put in the host's map.
func (*Config) FunctyTestCount ¶ added in v0.45.0
FunctyTestCount reports how many functy `test` blocks the compiled config declares. Used by `vinculum test` to distinguish "no tests" from "all tests filtered out" (for --fail-if-no-tests).
func (*Config) GetDefaultInstrumentMetrics ¶ added in v0.24.0
func (c *Config) GetDefaultInstrumentMetrics() (InstrumentMetrics, hcl.Diagnostics)
GetDefaultInstrumentMetrics returns the default InstrumentMetrics backend by searching both MetricsServers and OtlpClients. Selection rules:
- Exactly one candidate total → use it
- Multiple, exactly one with IsDefaultMetricsBackend()=true → use it
- Multiple with IsDefaultMetricsBackend()=true → config error
- Multiple, none default → return nil (explicit wiring required)
- Zero → return nil
func (*Config) GetDefaultMetricsRegistrar ¶ added in v0.20.0
func (c *Config) GetDefaultMetricsRegistrar() (MetricsRegistrar, hcl.Diagnostics)
GetDefaultMetricsRegistrar returns the default MetricsRegistrar per these rules:
- Exactly one metrics server → use it
- Multiple, exactly one with IsDefaultServer()=true → use it
- Multiple with IsDefaultServer()=true → config error
- Multiple, none default → return nil (explicit wiring required)
- Zero → return nil
func (*Config) GetDefaultOtlpClient ¶ added in v0.22.0
func (c *Config) GetDefaultOtlpClient() (OtlpClient, hcl.Diagnostics)
GetDefaultOtlpClient returns the default OtlpClient using these rules:
- Exactly one OTLP client → use it
- Multiple, exactly one with IsDefaultClient()=true → use it
- Multiple with IsDefaultClient()=true → config error
- Multiple, none default → return nil (explicit wiring required)
- Zero → return nil
func (*Config) GetFeature ¶ added in v0.19.0
GetFeature returns the value associated with a named feature flag, or empty string if the feature is not enabled.
func (*Config) GetFunctions ¶
func (c *Config) GetFunctions(userFuncs map[string]function.Function) (map[string]function.Function, hcl.Diagnostics)
GetFunctions builds the function map from all registered function plugins, then adds user-defined functions with duplicate detection.
func (*Config) GetMessageTransforms ¶
func (config *Config) GetMessageTransforms(expr hcl.Expression) (transforms []vbxform.MessageTransformFunc, diags hcl.Diagnostics)
func (*Config) ParseDuration ¶
func (c *Config) ParseDuration(expr hcl.Expression) (time.Duration, hcl.Diagnostics)
ParseDuration parses a duration from an HCL expression. It supports three formats: 1. Numbers (interpreted as seconds) 2. Strings starting with "P" (ISO 8601 durations using github.com/sosodev/duration) 3. Other strings (Go's native duration parsing)
func (*Config) ReconnectBackoffFunc ¶ added in v0.45.0
func (c *Config) ReconnectBackoffFunc(def *ReconnectDefinition) (func(int) time.Duration, hcl.Diagnostics)
ReconnectBackoffFunc lowers a reconnect block into the exponential backoff function that a protocol client library takes: attempt number in, wait duration out. Returns nil when there is no block, which every such library reads as "use your own default schedule".
This is one of two ways a reconnect block reaches a client, and what differs between them is the integration point, not the schedule. A bus client takes a bus.AutoReconnector, which owns the retry loop and can therefore stop — that is CreateReconnector below. A protocol client owns its own loop and only asks how long to wait next, so a func(int) time.Duration is all it can accept.
max_retries does not travel with the schedule, because giving up cannot be expressed in a duration. It is passed separately — see ReconnectMaxAttempts.
func (*Config) ResolveOtlpClient ¶ added in v0.22.0
func (c *Config) ResolveOtlpClient(expr hcl.Expression) (OtlpClient, hcl.Diagnostics)
ResolveOtlpClient returns the OtlpClient selected by expr (explicit wiring) or the default OTLP client (auto-wire). Returns nil with no error when no OTLP client is configured and no explicit tracing = is set.
func (*Config) ResolveTracerProvider ¶ added in v0.22.0
func (c *Config) ResolveTracerProvider(expr hcl.Expression) (trace.TracerProvider, hcl.Diagnostics)
ResolveTracerProvider returns the TracerProvider selected by expr (explicit wiring) or the default OTLP client (auto-wire). Returns nil with no error when no OTLP client is configured and no explicit tracing = is set.
func (*Config) RunTests ¶ added in v0.45.0
func (c *Config) RunTests(goctx context.Context, filter func(name string) bool) ([]functy.TestOutcome, error)
RunTests runs the config's functy `test` blocks against the live runtime eval context. The context is augmented with a top-level `ctx` (backed by goctx, and cancelable through it) so test bodies can call the many context-taking runtime functions — send, http, log::*, MCP builders, etc. functy's RunTestsMatching layers its own test-only builtins (skip/eventually/never) on top, so those resolve throughout each test's call graph while staying absent from a normal serve. filter==nil runs all tests; a nil slice (no error) is returned when the config declares no `test` blocks.
Conditions that observe async state must read it live — e.g. get(var.x) — so re-evaluation by eventually/never sees mutations by subscription actions: a VCL `var` is a capsule over a shared *types.Variable, dereferenced at each get().
func (*Config) SetSignalAction ¶
func (config *Config) SetSignalAction(sigName string, action hcl.Expression) hcl.Diagnostics
func (*Config) SourceFiles ¶ added in v0.45.0
SourceFiles exposes every source file the configuration was built from (filename → bytes: .vinit, .vcl, and .cty) so a caller such as `vinculum test` can render a failure's diagnostics with source context. Returns nil for a Config not produced by Build — hcl's diagnostic writer tolerates a nil map.
type ConfigBuilder ¶
type ConfigBuilder struct {
// contains filtered or unexported fields
}
func NewConfig ¶
func NewConfig() *ConfigBuilder
func (*ConfigBuilder) Build ¶
func (cb *ConfigBuilder) Build() (*Config, hcl.Diagnostics)
func (*ConfigBuilder) Files ¶ added in v0.45.0
func (cb *ConfigBuilder) Files() map[string]*hcl.File
Files returns the source files parsed by the most recent Build(), keyed by filename, for rendering that Build's diagnostics with the offending line quoted (hcl.NewDiagnosticTextWriter takes exactly this map). It is populated as each pass parses, so it is complete for the failure at hand whether or not Build() returned a Config. Returns nil before the first Build.
func (*ConfigBuilder) GetBlocks ¶
func (cb *ConfigBuilder) GetBlocks(bodies []hcl.Body) (hcl.Blocks, hcl.Diagnostics)
GetBlocks collects the top-level blocks of each body. The schema is closed: the bodies passed here have already had the function-definition blocks (function, jq, editor, procedure) taken out of them, so anything still unaccounted for is a typo or a stray attribute and is reported rather than silently ignored. HCL supplies the "Did you mean" suggestion against the known block types.
func (*ConfigBuilder) SortBlocksByDependencies ¶
func (cb *ConfigBuilder) SortBlocksByDependencies(blocks hcl.Blocks, handlers map[string]BlockHandler) (hcl.Blocks, hcl.Diagnostics)
SortBlocksByDependencies returns blocks sorted in dependency order using Kahn's algorithm. When multiple blocks are available (no ordering constraint between them), they are emitted in their original source order. Blocks without a dependency ID (const, signals, function) are appended at the end unchanged. handlers must be the same BlockHandler instances that had FinishPreprocessing called on them, so per-build handler state (e.g. conditional trigger registry) is visible during dependency resolution.
func (*ConfigBuilder) WithFeature ¶ added in v0.19.0
func (c *ConfigBuilder) WithFeature(name, value string) *ConfigBuilder
WithFeature enables a named feature flag with the given value. Use an empty value to disable a previously set feature. Known features: "readfiles" (value = --file-path dir),
"writefiles" (value = --write-path dir), "allowkill" (value = "true").
func (*ConfigBuilder) WithLogger ¶
func (c *ConfigBuilder) WithLogger(logger *zap.Logger) *ConfigBuilder
func (*ConfigBuilder) WithPluginPath ¶ added in v0.37.0
func (c *ConfigBuilder) WithPluginPath(path string) *ConfigBuilder
WithPluginPath sets the directory from which `plugin "<label>" { ... }` blocks resolve their .so files. The empty string (default) means plugins are not permitted: any `plugin` block encountered in a .vinit file will produce a fatal diagnostic.
func (*ConfigBuilder) WithSources ¶
func (c *ConfigBuilder) WithSources(sources ...any) *ConfigBuilder
func (*ConfigBuilder) WithTesting ¶ added in v0.45.0
func (c *ConfigBuilder) WithTesting(testing bool) *ConfigBuilder
WithTesting marks the build as a test run (`vinculum test`). When true, the `sys.testing` ambient is true, letting a config disable real external connections under test via `disabled = sys.testing`. Must be set before Build(), since `sys.testing` is consumed while blocks are processed.
type ConstBlockHandler ¶
type ConstBlockHandler struct {
BlockHandlerBase
// contains filtered or unexported fields
}
func NewConstBlockHandler ¶
func NewConstBlockHandler() *ConstBlockHandler
func (*ConstBlockHandler) FinishPreprocessing ¶
func (b *ConstBlockHandler) FinishPreprocessing(config *Config) hcl.Diagnostics
func (*ConstBlockHandler) Preprocess ¶
func (b *ConstBlockHandler) Preprocess(block *hcl.Block) hcl.Diagnostics
func (*ConstBlockHandler) Schema ¶ added in v0.45.0
func (b *ConstBlockHandler) Schema() TypeSchema
Schema describes the const block for `vinculum schema`.
type Constraint ¶ added in v0.45.0
type Constraint struct {
Kind ConstraintKind `json:"kind"`
Attributes []string `json:"attributes"`
Message string `json:"message"`
}
Constraint is an advisory cross-attribute rule. Editors surface constraints as documentation or diagnostics; the Go decode/validate path remains the authority.
func AtLeastOneOf ¶ added in v0.45.0
func AtLeastOneOf(attrs ...string) Constraint
AtLeastOneOf declares that at least one of the named attributes must be set.
func MutuallyExclusive ¶ added in v0.45.0
func MutuallyExclusive(attrs ...string) Constraint
MutuallyExclusive declares that at most one of the named attributes may be set.
func RequiredTogether ¶ added in v0.45.0
func RequiredTogether(attrs ...string) Constraint
RequiredTogether declares that the named attributes must all be set, or none.
func Requires ¶ added in v0.45.0
func Requires(attr string, requires ...string) Constraint
Requires declares that setting attr implies setting all of requires.
func (Constraint) WithMessage ¶ added in v0.45.0
func (c Constraint) WithMessage(msg string) Constraint
WithMessage returns a copy of the constraint with a custom message, replacing the generated default.
type ConstraintKind ¶ added in v0.45.0
type ConstraintKind string
ConstraintKind identifies a cross-attribute rule.
const ( // ConstraintMutuallyExclusive means at most one of the attributes may be set. ConstraintMutuallyExclusive ConstraintKind = "mutually_exclusive" // ConstraintAtLeastOneOf means at least one of the attributes must be set. ConstraintAtLeastOneOf ConstraintKind = "at_least_one_of" // ConstraintRequiredTogether means the attributes must all be set, or none. ConstraintRequiredTogether ConstraintKind = "required_together" // ConstraintRequires means the first attribute implies all the others. ConstraintRequires ConstraintKind = "requires" )
type ContextField ¶ added in v0.45.0
type ContextField struct {
// Name is the attribute name, read as `ctx.<name>`.
Name string
// Type is the coarse value type, from the same vocabulary as an
// attribute's: string, number, bool, list, map, or object — plus "dynamic"
// for a value whose type depends on the message, and "capsule" for an
// opaque handle passed to a function rather than read directly.
Type string
// Summary is a one-line description, shown as a completion item's detail.
Summary string
// Doc is richer Markdown for hover.
Doc string
// Optional marks a field that is absent from some evaluations of this
// shape, e.g. ctx.fields on a message that carries no metadata.
Optional bool
}
ContextField is one field of a `ctx` shape.
type ContextSchema ¶ added in v0.45.0
type ContextSchema struct {
// Summary is a one-line description of when an expression sees this shape.
Summary string
// Doc is richer Markdown for hover.
Doc string
// Fields are the shape's own fields, in the order worth reading them.
Fields []ContextField
// OpenFields marks a shape whose Fields are a floor rather than the whole
// list: every site carries them, and a site may carry more. Attributes
// naming an open shape declare their additions with
// AttrMeta.ContextFields; only an open shape may.
//
// `decode-error` is the case — five fields are fixed by
// MakeDecodeErrorHook and the receiver adds its own transport identity —
// and a consumer that treated the list as closed would report a correct
// `ctx.routing_key` as an unknown field.
OpenFields bool
}
ContextSchema describes one shape of `ctx`: what an expression evaluated at that kind of site can read. Shapes are named by AttrMeta.Context and registered with RegisterContextSchema.
Unlike the rest of the structural layer there is no reflection source — a `ctx` is assembled imperatively by an hclutil.EvalContextBuilder chain — so Fields is written by hand. Keep it beside the code that builds the context so the two are read and edited together. The universal fields (auth, baggage, trace_id, span_id) are supplied by the generator and must not be repeated: every `ctx` goes through hclutil, which is what puts them there, and there is deliberately no way to describe a shape that lacks them. A site that would need one is a site that should be building its context through hclutil.
type CtyValuer ¶ added in v0.16.0
CtyValuer is an optional interface that Client implementations may satisfy to provide a custom cty value for the eval context. If not implemented, the client is wrapped in a plain ClientCapsule.
type CtyWireFormat ¶ added in v0.30.0
type CtyWireFormat struct {
Inner wire.WireFormat
}
CtyWireFormat wraps a WireFormat with cty conversion.
On the serialize side, if the input is a cty.Value it is converted to native Go types via go2cty2go.CtyToAny before delegating; any other type passes straight through to the inner WireFormat. A bytes value converts to its raw []byte there (via the go2cty2go conversion interface bytescty implements), so it is sent unchanged.
On the deserialize side, the inner WireFormat's native Go output is converted to a cty.Value via go2cty2go.AnyToCty — except for []byte, which becomes a rich bytes object (see below).
CtyWireFormat itself satisfies the WireFormat interface (Serialize takes any, Deserialize returns any), so it composes transparently.
func (*CtyWireFormat) Deserialize ¶ added in v0.30.0
func (f *CtyWireFormat) Deserialize(b []byte) (any, error)
func (*CtyWireFormat) Name ¶ added in v0.30.0
func (f *CtyWireFormat) Name() string
func (*CtyWireFormat) Serialize ¶ added in v0.30.0
func (f *CtyWireFormat) Serialize(v any) ([]byte, error)
func (*CtyWireFormat) SerializeString ¶ added in v0.30.0
func (f *CtyWireFormat) SerializeString(v any) (string, error)
type EditorDefinition ¶ added in v0.23.0
type EditorDefinition struct {
Type string
Name string
Params []string // parameter names extracted from params expression
VariadicParam string // optional variadic parameter name
Body hcl.Body // remaining body for type-specific parsing
DefRange hcl.Range
}
EditorDefinition holds the parsed outer editor block, common across all editor types.
type EditorProcessor ¶ added in v0.23.0
type EditorProcessor func( config *Config, evalCtxFn func() *hcl.EvalContext, def *EditorDefinition, ) (function.Function, hcl.Diagnostics)
EditorProcessor compiles an editor block's type-specific body into a cty function. It is called once per editor block during early config processing.
type ErrorlessStartable ¶
type ErrorlessStartable struct {
// contains filtered or unexported fields
}
func (ErrorlessStartable) Start ¶
func (e ErrorlessStartable) Start() error
type FileKind ¶ added in v0.45.0
type FileKind string
FileKind says which kind of configuration file a top-level block belongs in.
Vinculum reads two languages: `.vcl`, the configuration language proper, and `.vinit`, the bootstrap format processed before any `.vcl` is parsed. They have separate closed schemas, so a block of one is an error in the other. The document describes both in one `blocks` map — a block type name means one thing whatever file it is written in, and a topic path has one namespace to resolve in — and this is what tells them apart.
type FsmBlockHandler ¶ added in v0.33.0
type FsmBlockHandler struct {
BlockHandlerBase
// contains filtered or unexported fields
}
FsmBlockHandler processes fsm blocks.
func NewFsmBlockHandler ¶ added in v0.33.0
func NewFsmBlockHandler() *FsmBlockHandler
func (*FsmBlockHandler) FinishPreprocessing ¶ added in v0.33.0
func (h *FsmBlockHandler) FinishPreprocessing(config *Config) hcl.Diagnostics
FinishPreprocessing creates placeholder instances and populates the capsule map so that fsm.<name> references can be resolved during dependency analysis. Process() later calls inst.Configure() to replace the placeholder definition with the real one -- this works because the capsule wraps a pointer to the Instance, so all resolved references see the updated state.
func (*FsmBlockHandler) GetBlockDependencies ¶ added in v0.33.0
func (h *FsmBlockHandler) GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
func (*FsmBlockHandler) GetBlockDependencyId ¶ added in v0.33.0
func (h *FsmBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
func (*FsmBlockHandler) Preprocess ¶ added in v0.33.0
func (h *FsmBlockHandler) Preprocess(block *hcl.Block) hcl.Diagnostics
Preprocess validates the block and registers the FSM name for duplicate detection. The actual instance is created in FinishPreprocessing.
func (*FsmBlockHandler) Process ¶ added in v0.33.0
func (h *FsmBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
func (*FsmBlockHandler) Schema ¶ added in v0.45.0
func (h *FsmBlockHandler) Schema() TypeSchema
Schema describes the fsm block for `vinculum schema`.
type FsmTopLevel ¶ added in v0.33.0
type FsmTopLevel struct {
Name string `hcl:"name,label"`
Initial string `hcl:"initial"`
QueueSize *int `hcl:"queue_size,optional"`
ShutdownEvent *string `hcl:"shutdown_event,optional"`
Disabled bool `hcl:"disabled,optional"`
Tracing hcl.Expression `hcl:"tracing,optional"`
OnChange hcl.Expression `hcl:"on_change,optional"`
OnError hcl.Expression `hcl:"on_error,optional"`
RemainingBody hcl.Body `hcl:",remain"`
}
FsmTopLevel is the gohcl-decoded envelope for an fsm block. Sub-blocks (state, event, storage) are parsed manually from RemainingBody because we need declaration-order iteration and raw hcl.Expression access.
type FuncDoc ¶ added in v0.45.0
type FuncDoc struct {
Name string
// Signatures is one rendered calling convention per form. More than one
// means an overload set: a host function whose argument shapes differ per
// arity is not one function with optional parameters, and showing it as one
// would lie.
Signatures []string
// Doc is the prose describing the function, "" when undocumented.
Doc string
// Params are the documented parameters, unioned across the forms with the
// first occurrence of a name winning — matching how functy renders them.
Params []FuncParam
}
FuncDoc is a function's documentation.
type FuncParam ¶ added in v0.45.0
type FuncParam struct {
// Name is how the parameter is written in a signature: "*rest" for a
// variadic, "name?" for one that is optional with no default, else the bare
// name.
Name string
// Type is the annotated type, "" when unannotated (dynamic).
Type string
// Default is the source text of a default value, "" when there is none.
Default string
// Doc describes the parameter, "" when undocumented.
Doc string
// Required reports whether a caller must supply it.
Required bool
}
FuncParam is one parameter of a function.
type FunctionPlugin ¶ added in v0.19.0
FunctionPlugin returns a map of functions for the given config. Plugins that don't need config can ignore the cfg parameter. Conditional plugins (e.g. filesystem, filewrite) return nil when their required feature is not enabled.
type GitAuth ¶ added in v0.39.0
type GitAuth struct {
Token string `hcl:"token,optional"`
Username string `hcl:"username,optional"`
Password string `hcl:"password,optional"`
PrivateKey string `hcl:"private_key,optional"`
PrivateKeyFile string `hcl:"private_key_file,optional"`
Passphrase string `hcl:"passphrase,optional"`
KnownHosts string `hcl:"known_hosts,optional"`
InsecureIgnoreHostKey bool `hcl:"insecure_ignore_host_key,optional"`
DefRange hcl.Range `hcl:",def_range"`
}
GitAuth holds the optional credentials for a git block. Which attributes are valid depends on the transport inferred from the repo URL scheme (HTTP(S) vs SSH); see validateGitAuth.
type GitDefinition ¶ added in v0.39.0
type GitDefinition struct {
Label string `hcl:"name,label"`
Disabled bool `hcl:"disabled,optional"`
Repo string `hcl:"repo"`
Branch string `hcl:"branch,optional"`
Tag string `hcl:"tag,optional"`
Commit string `hcl:"commit,optional"`
Depth *int `hcl:"depth,optional"`
Submodules bool `hcl:"submodules,optional"`
Auth *GitAuth `hcl:"auth,block"`
Fetches []GitFetch `hcl:"fetch,block"`
DefRange hcl.Range `hcl:",def_range"`
}
GitDefinition is the structural decode of a `git "<label>" { ... }` block in a .vinit file. It clones a remote repository during bootstrap pass 1 and materializes one or more subtrees onto the local filesystem before any .vcl is parsed.
type GitFetch ¶ added in v0.39.0
type GitFetch struct {
Name string `hcl:"name,label"`
From string `hcl:"from,optional"`
Into string `hcl:"into"`
Overwrite bool `hcl:"overwrite,optional"`
DefRange hcl.Range `hcl:",def_range"`
}
GitFetch copies one subtree of the cloned repository to one local destination. A git block has one or more fetch sub-blocks sharing a single clone.
type HandlerServer ¶
HandlerServer is a Listener that can serve HTTP requests when mounted into an HTTP server block via a handle block.
type HelpTopicResolver ¶ added in v0.45.0
type HelpTopicResolver interface {
// HelpKinds returns the kind names this resolver accepts, which are what
// may appear as a `kind:` prefix — "block:http" to ask for the block when
// a bare "http" would be ambiguous.
HelpKinds() []string
// HelpTopic renders the topic named by path, already formatted for
// reading. An empty kind searches every kind.
//
// The bool distinguishes "nothing is named that" from "here is the answer".
// An ambiguous path is an answer: the rendered menu of ways to resolve it.
HelpTopic(kind string, path []string) (string, bool)
}
HelpTopicResolver documents the topics that are not functions: block types, their variants and members, and `ctx` shapes.
type Hint ¶ added in v0.45.0
type Hint string
Hint is a member of a closed vocabulary describing what kind of value an attribute takes, so a completion provider can offer the right candidates. The provider — not Vinculum — knows how to expand each hint.
const ( // HintExpression is a generic expression, evaluated for its value against // the global namespace — const, var, metric, functions — with no `ctx`. // Usually that happens once at config load; a few attributes (a computed // metric's `value`) are polled at runtime but see the same namespace, and // say so in their own docs. HintExpression Hint = "expression" // HintActionExpression is an action: an expression // evaluated at event time rather than config time, largely for its side // effects — logging, sending messages, setting variables — with a // block-specific `ctx` in scope. In list form each element is evaluated in // order and the last value is the result. HintActionExpression Hint = "action-expression" // HintPredicateExpression is a predicate: evaluated at event time like an // action, with the same block-specific `ctx` in scope, but for its boolean // value rather than its side effects — an fsm transition `guard`, a // trigger's `skip_when`/`stop_when`, a server's `allow_send`. A completion // provider should offer `ctx.*` and comparisons here, not the // side-effecting functions an action wants. HintPredicateExpression Hint = "predicate-expression" // HintReactiveExpression is a reactive expression: it is re-evaluated for // its value automatically whenever any watchable it references changes — a // var, metric, condition, or fsm — rather than once at config time or in // response to an event. It has no `ctx`, and what it references is what // makes it fire, so a completion provider should offer watchable // references here. See config.ReactiveExpr. HintReactiveExpression Hint = "reactive-expression" // HintTransformPipeline is a list of transform functions applied in order // to each message before delivery — `add_topic_prefix("out/")`, `jq(...)`, // `if_topic_prefix(...)`, `stop()`, and so on. // // The transform functions are a DSL, not part of the general expression // language: they exist only in the eval context of attributes that expect // a transform list. A completion provider should offer those functions // here, and only those. HintTransformPipeline Hint = "transform-pipeline" // HintBusRef is a reference to a bus specifically — a slot that resolves // an event bus and nothing else. For the much more common slot that takes // anything able to receive messages, use HintSubscriberRef. HintBusRef Hint = "bus-ref" // HintSubscriberRef is a reference to anything that can receive messages: // any capsule whose value implements bus.Subscriber. That includes buses // (`bus.<name>`) but also FSMs, subscriber-implementing servers such as // `server "vws"` and `server "websocket"`, and clients that publish // outbound. A completion provider should offer all of them, not just // `bus.*`. HintSubscriberRef Hint = "subscriber-ref" // HintClientRef is a `client.<name>` reference. HintClientRef Hint = "client-ref" // HintServerRef is a `server.<name>` reference. HintServerRef Hint = "server-ref" // HintMetricRef is a `metric.<name>` reference. HintMetricRef Hint = "metric-ref" // HintTracingRef is a reference to a tracing backend: a `client "otlp"` // block. Narrower than HintClientRef, which would offer every client. HintTracingRef Hint = "tracing-ref" // HintMetricsRef is a reference to a metrics backend: a `server "metrics"` // or a `client "otlp"` block. Narrower than HintServerRef/HintClientRef, // and it spans both namespaces, which neither of those can express. HintMetricsRef Hint = "metrics-ref" // HintVarRef is a `var.<name>` reference. HintVarRef Hint = "var-ref" // HintTopicPattern is an MQTT-style topic pattern (`+`, `#`). HintTopicPattern Hint = "topic-pattern" // HintCronExpr is a cron expression. HintCronExpr Hint = "cron-expr" // HintDuration is a Go duration literal ("5s", "1h"). HintDuration Hint = "duration" // HintURL is a URL. HintURL Hint = "url" // HintListenAddr is a `:port` or `host:port` listen address. HintListenAddr Hint = "listen-addr" // HintBool is `true` / `false`. HintBool Hint = "bool" )
type InstrumentMetrics ¶ added in v0.24.0
type InstrumentMetrics interface {
GetMeterProvider() metric.MeterProvider
IsDefaultMetricsBackend() bool
}
InstrumentMetrics is satisfied by both server "metrics" and client "otlp". Used to resolve the metrics MeterProvider for metric blocks and server auto-instrumentation.
func GetInstrumentMetricsFromExpression ¶ added in v0.24.0
func GetInstrumentMetricsFromExpression(config *Config, expr hcl.Expression) (InstrumentMetrics, hcl.Diagnostics)
GetInstrumentMetricsFromExpression evaluates an HCL expression and returns it as an InstrumentMetrics. The expression may reference either a server "metrics" block or a client "otlp" block.
type Listener ¶
func GetServerFromCapsule ¶
GetServerFromCapsule extracts an Server from a cty capsule value
func GetServerFromExpression ¶
func GetServerFromExpression(config *Config, busExpr hcl.Expression) (Listener, hcl.Diagnostics)
type MemberMeta ¶ added in v0.45.0
type MemberMeta struct {
// Summary is a one-line description, shown as a completion item's detail.
Summary string
// Doc is richer Markdown for hover.
Doc string
// Members describes the members of a member that is itself an object
// (`sys.functy.version`). An object member must set this or FreeMembers, so
// that gaining a field is a reported change rather than a silent one.
Members map[string]MemberMeta
// FreeMembers marks an object member whose names are not fixed by the
// language — `sys.signals` carries whichever signals the host OS defines.
// As on a namespace, Members is then a floor: `sys.signals.bynumber` is
// described and always present, while the signal names beside it vary with
// the OS and are neither enumerated nor checked.
FreeMembers bool
}
MemberMeta is curated metadata for a single member of a namespace.
type MessageConverter ¶
MessageConverter defines how to convert a cty.Value message before sending
type MessageTransformWrapper ¶
type MessageTransformWrapper struct {
Func vbxform.MessageTransformFunc
}
MessageTransformWrapper wraps a MessageTransformFunc for use in cty capsules
type MetricBlockHandler ¶ added in v0.13.0
type MetricBlockHandler struct {
BlockHandlerBase
// contains filtered or unexported fields
}
func NewMetricBlockHandler ¶ added in v0.13.0
func NewMetricBlockHandler() *MetricBlockHandler
func (*MetricBlockHandler) FinishPreprocessing ¶ added in v0.13.0
func (h *MetricBlockHandler) FinishPreprocessing(config *Config) hcl.Diagnostics
func (*MetricBlockHandler) GetBlockDependencies ¶ added in v0.13.0
func (h *MetricBlockHandler) GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
func (*MetricBlockHandler) GetBlockDependencyId ¶ added in v0.13.0
func (h *MetricBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
func (*MetricBlockHandler) Preprocess ¶ added in v0.13.0
func (h *MetricBlockHandler) Preprocess(block *hcl.Block) hcl.Diagnostics
func (*MetricBlockHandler) Process ¶ added in v0.13.0
func (h *MetricBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
func (*MetricBlockHandler) Schema ¶ added in v0.45.0
func (h *MetricBlockHandler) Schema() TypeSchema
Schema describes the metric block for `vinculum schema`. The metric type is a block label like any other typed block, but there is no registry behind it — Preprocess accepts a fixed set — so the variants are declared here.
func (*MetricBlockHandler) SetImplicitBackendDeps ¶ added in v0.26.0
func (h *MetricBlockHandler) SetImplicitBackendDeps(ids []string)
SetImplicitBackendDeps records the dependency IDs of server "metrics" and client "otlp" blocks so that metric blocks without an explicit server attribute are ordered after them.
type MetricDefinition ¶ added in v0.13.0
type MetricDefinition struct {
Help string `hcl:"help"`
LabelNames []string `hcl:"label_names,optional"`
Namespace string `hcl:"namespace,optional"`
Buckets []float64 `hcl:"buckets,optional"`
Server hcl.Expression `hcl:"server,optional"`
Value hcl.Expression `hcl:"value,optional"`
ComputedInterval *string `hcl:"computed_interval,optional"`
Tracing hcl.Expression `hcl:"tracing,optional"`
DefRange hcl.Range `hcl:",def_range"`
}
MetricDefinition holds the decoded HCL body of a metric block.
type MetricsRegistrar ¶ added in v0.20.0
type MetricsRegistrar interface {
Listener
InstrumentMetrics
GetRegistry() *prometheus.Registry
IsDefaultServer() bool
}
MetricsRegistrar is implemented by server types that provide a Prometheus registry for metric blocks to register against.
func GetMetricsRegistrarFromExpression ¶ added in v0.20.0
func GetMetricsRegistrarFromExpression(config *Config, expr hcl.Expression) (MetricsRegistrar, hcl.Diagnostics)
GetMetricsRegistrarFromExpression evaluates an HCL expression expecting a server capsule and returns it as a MetricsRegistrar. Returns an error if the server does not implement MetricsRegistrar.
type NamespaceSchema ¶ added in v0.45.0
type NamespaceSchema struct {
// Block names the top-level block type that publishes names into this
// namespace, for a namespace the config author fills in (`bus.<name>`).
// Setting it makes the namespace a block namespace, which has no members of
// its own to enumerate.
Block string
// Summary is a one-line description, used as a completion item's detail.
Summary string
// Doc is richer Markdown used for hover; may be multi-paragraph.
Doc string
// DocPage names the hand-written reference page for this namespace,
// relative to doc/, as TypeSchema.DocPage does.
DocPage string
// Members holds curated per-member metadata, keyed by member name. Every
// key must name a member the provider's value carries, and every member it
// carries must have an entry.
Members map[string]MemberMeta
// FreeMembers marks a namespace whose member names are not the language's
// to know: `env` is the environment of whichever process happens to be
// running, so enumerating it would describe the machine that generated the
// document rather than the language.
//
// Members is then a floor rather than the whole list — whatever is
// described is described, and anything else is allowed. Nothing undescribed
// is emitted, which is also what keeps the document from varying with the
// machine that produced it, and `vinculum check` accepts any name below
// such a root.
FreeMembers bool
// Constant marks a namespace whose values are identical in every process,
// so the value is part of the language rather than of the environment and
// is emitted alongside the member. True of `http_status`; false of `sys`,
// whose hostname and pid describe the machine.
Constant bool
// UniformMemberSummary is the summary taken by every member that does not
// carry its own. It exists for a namespace whose members are a single
// uniform family — `http_status` is sixty status codes that differ only in
// which code they are — where sixty hand-written summaries would say the
// same sentence sixty times and hide the one fact that differs.
//
// Only legal together with Constant, because the emitted value is then what
// distinguishes one member from another. Without it the members would be
// documented and indistinguishable.
UniformMemberSummary string
}
NamespaceSchema is curated metadata for one top-level name in the evaluation namespace.
For a provider namespace it is registered next to the provider:
cfg.RegisterAmbientProvider("sys", provide, cfg.WithNamespaceSchema(sysNamespace))
and Members is validated against the value the provider actually returns, in both directions — the same contract a block's attributes get.
type OtlpClient ¶ added in v0.22.0
type OtlpClient interface {
Client
// GetTracerProvider returns the OTel SDK TracerProvider for span extraction
// (e.g. to call tracer.Start() or trace.SpanFromContext()).
GetTracerProvider() trace.TracerProvider
// IsDefaultClient returns true if this client should be used when no
// explicit tracing = attribute is specified.
IsDefaultClient() bool
// GetMeterProvider returns the OTel SDK MeterProvider for creating
// metric instruments (counters, histograms, gauges).
GetMeterProvider() metric.MeterProvider
// IsDefaultMetricsBackend returns true if this client should be used
// as the default metrics backend when no explicit metrics = is specified.
IsDefaultMetricsBackend() bool
}
OtlpClient is implemented by client "otlp" blocks. It provides both tracing and push metrics via the o11y abstractions, so it can satisfy metrics = and tracing = attributes on servers.
func GetOtlpClientFromExpression ¶ added in v0.22.0
func GetOtlpClientFromExpression(config *Config, expr hcl.Expression) (OtlpClient, hcl.Diagnostics)
GetOtlpClientFromExpression evaluates an HCL expression expecting a client capsule and returns it as an OtlpClient. Returns an error if the client does not implement OtlpClient.
type PluginContext ¶ added in v0.37.0
type PluginContext struct {
// Block is the `plugin "<label>" { ... }` block as parsed from the
// .vinit file. Block.Labels[0] is the plugin label. Block.Body is the
// full block body; the plugin decodes its own schema from it. The
// `disabled` attribute has already been consumed by Vinculum but is
// still syntactically present in the body.
Block *hcl.Block
// EvalContext is the minimal .vinit eval context: env.* and the cty
// standard library. No const, no user functions, no contributions from
// other plugins.
EvalContext *hcl.EvalContext
// Logger is a zap logger pre-bound with `plugin=<label>` as a
// structured field. Plugins should use this rather than constructing
// their own logger so plugin output is consistent with Vinculum's.
// May be nil if Vinculum was started without a logger.
Logger *zap.Logger
}
PluginContext is the single argument passed to a Go plugin's VinculumPluginInit entry point. New fields may be appended in future releases to grow the surface without breaking existing plugins; existing fields will not change type.
type PluginDefinition ¶ added in v0.37.0
type PluginDefinition struct {
Label string `hcl:"name,label"`
Disabled bool `hcl:"disabled,optional"`
Body hcl.Body `hcl:",remain"`
}
PluginDefinition is the structural decode of a `plugin "<label>" { ... }` block in a .vinit file. Disabled is consumed by Vinculum; the remaining body is handed to the plugin's VinculumPluginInit for its own decoding.
type PostStartable ¶ added in v0.21.0
type PostStartable interface {
PostStart() error
}
PostStartable is implemented by components that need to run logic after all Startable components have completed their Start() calls. PostStart() is called once, in the same order as Start(), after the full startup sequence completes.
type PreStoppable ¶ added in v0.22.0
type PreStoppable interface {
PreStop() error
}
PreStoppable is implemented by components that need to run logic before any Stoppable components have their Stop() called. PreStop() is called in reverse registration order, before the full teardown sequence begins. This guarantees that the full runtime environment (clients, buses, subscriptions) is still available when PreStop() executes.
type ReactiveExpr ¶ added in v0.27.0
type ReactiveExpr struct {
// contains filtered or unexported fields
}
ReactiveExpr wraps an HCL expression that must be re-evaluated whenever any Watchable it references changes — the mechanism behind condition block input = and inhibit = attributes.
Unlike a one-shot gohcl.DecodeBody, ReactiveExpr extracts every Watchable referenced by the expression at construction time, subscribes to each as a Watcher on Start(), and invokes a callback with the re-evaluated value on every change. Stop() unsubscribes. Construction is cheap; Start() is the point at which the caller commits to receiving callbacks.
Circular references between blocks are rejected at config load time by the existing block-level dependency DAG (ExtractBlockDependencies walks the block body and Kahn's sort fails on cycles), so ReactiveExpr itself does not need additional cycle detection.
func NewReactiveExpr ¶ added in v0.27.0
func NewReactiveExpr(expr hcl.Expression, evalCtx *hcl.EvalContext, callback func(ctx context.Context, value cty.Value)) (*ReactiveExpr, hcl.Diagnostics)
NewReactiveExpr constructs a ReactiveExpr by extracting every Watchable referenced by expr against evalCtx. callback is invoked with the current value on Start(), and again whenever any source Watchable's value changes.
References that do not resolve to a Watchable capsule (constants, plain cty values, env references, etc.) are silently ignored — the expression may freely mix reactive and static inputs. If a reference cannot be resolved at all, a diagnostic is returned; the returned ReactiveExpr is still usable (it just won't fire for that branch).
func (*ReactiveExpr) Eval ¶ added in v0.27.0
func (r *ReactiveExpr) Eval() (cty.Value, hcl.Diagnostics)
Eval re-evaluates the expression against the current eval context and returns the resulting value.
func (*ReactiveExpr) OnChange ¶ added in v0.27.0
OnChange implements richcty.Watcher. When any source Watchable changes, the expression is re-evaluated and the callback is invoked with the new value. Evaluation errors are swallowed here (the previous value remains in effect from the caller's perspective); config-time errors surface at Start().
func (*ReactiveExpr) Sources ¶ added in v0.27.0
func (r *ReactiveExpr) Sources() []richcty.Watchable
Sources returns the list of Watchables this expression depends on. Useful for tests and introspection.
func (*ReactiveExpr) Start ¶ added in v0.27.0
func (r *ReactiveExpr) Start(ctx context.Context) hcl.Diagnostics
Start subscribes to every source Watchable and invokes the callback with the expression's current value. Idempotent.
func (*ReactiveExpr) Stop ¶ added in v0.27.0
func (r *ReactiveExpr) Stop()
Stop unsubscribes from every source Watchable. Idempotent.
type ReconnectDefinition ¶ added in v0.10.0
type ReconnectDefinition struct {
InitialDelay hcl.Expression `hcl:"initial_delay,optional"`
MaxDelay hcl.Expression `hcl:"max_delay,optional"`
BackoffFactor *float64 `hcl:"backoff_factor,optional"`
MaxRetries *int `hcl:"max_retries,optional"`
DefRange hcl.Range `hcl:",def_range"`
// BackoffFactorRange underlines the attribute itself when its value is
// rejected. A *float64 carries no range of its own, and pointing at the
// whole block would leave a reader of a five-attribute block looking for
// which one was meant.
BackoffFactorRange hcl.Range `hcl:"backoff_factor,attr_range"`
}
type RegisterOption ¶ added in v0.45.0
type RegisterOption func(*registerOptions)
RegisterOption customizes a Register*Type call. Supplying a schema is optional and additive: a type registered without one still appears in the output, flagged "undocumented", so coverage gaps are visible rather than invisible.
func WithNamespaceSchema ¶ added in v0.45.0
func WithNamespaceSchema(ns NamespaceSchema) RegisterOption
WithNamespaceSchema attaches the machine-readable description of the top-level namespace an ambient provider contributes:
cfg.RegisterAmbientProvider("sys", provide, cfg.WithNamespaceSchema(sysNamespace))
func WithSchema ¶ added in v0.45.0
func WithSchema(ts TypeSchema) RegisterOption
WithSchema attaches the machine-readable schema of the type being registered. It is called from inside the defining package's init(), where the (usually unexported) decode struct is in scope:
cfg.RegisterClientType("http", process, cfg.WithSchema(httpClientSchema))
func WithVariantSchemas ¶ added in v0.45.0
func WithVariantSchemas(schemas map[string]TypeSchema) RegisterOption
WithVariantSchemas attaches schemas for a set of type names registered together. It exists for RegisterConditionalTriggerType, whose factory cannot be invoked without a *Config and so cannot reveal its type names any other way.
type SchemaAttr ¶ added in v0.45.0
type SchemaAttr struct {
Name string `json:"name"`
Required bool `json:"required"`
// Type is the coarse value type: expression, string, bool, number, list,
// or map.
Type string `json:"type"`
Summary string `json:"summary,omitempty"`
Doc string `json:"doc,omitempty"`
Hint Hint `json:"hint,omitempty"`
// Context names the `ctx` shape this attribute's expression sees; look it
// up in the document's top-level `contexts`.
Context string `json:"context,omitempty"`
// ContextFields are fields this site adds to that shape, present only for
// an open shape. Read them as appended to the shape's own fields.
ContextFields []*SchemaContextField `json:"contextFields,omitempty"`
Enum []string `json:"enum,omitempty"`
// Default is the value used when the attribute is omitted, written as it
// would be written in a config file. Absent when there is no default worth
// stating rather than when the zero value applies.
Default string `json:"default,omitempty"`
Deprecated string `json:"deprecated,omitempty"`
}
SchemaAttr describes one HCL attribute.
type SchemaBlock ¶ added in v0.45.0
type SchemaBlock struct {
// File is the kind of configuration file this block belongs in. Always
// emitted, so a consumer validating one language cannot mistake a block of
// the other for one of its own.
File FileKind
// Labels are the block's label names, from blockSchema.
Labels []string
// VariantLabel names the label that selects the variant; empty for plain
// blocks. Always the first label in v1.
VariantLabel string
// Summary and Doc describe the block type as a whole.
Summary string
Doc string
// DocPage is the hand-written reference page for the block type.
DocPage string
// Undocumented is true when no curated schema was registered for the block.
Undocumented bool
// Body is the single body of a plain block; nil for typed blocks.
Body *SchemaBody
// Variants maps variant key to body; nil for plain blocks.
Variants map[string]*SchemaBody
}
SchemaBlock describes one top-level block type. It has two shapes: a plain block inlines a single Body, while a typed block (one whose first label selects a variant, e.g. `client "http"`) carries a map of variant bodies instead.
func (SchemaBlock) MarshalJSON ¶ added in v0.45.0
func (b SchemaBlock) MarshalJSON() ([]byte, error)
MarshalJSON emits the plain or typed shape depending on whether the block has a variant dimension.
type SchemaBody ¶ added in v0.45.0
type SchemaBody struct {
Summary string `json:"summary,omitempty"`
Doc string `json:"doc,omitempty"`
// DocPage is the hand-written reference page for this type, relative to
// doc/. A consumer generating an index links to it.
DocPage string `json:"docPage,omitempty"`
// Undocumented is true when no curated schema was registered for this body.
Undocumented bool `json:"undocumented,omitempty"`
// Conditional is true for a variant whose availability depends on config
// state (see RegisterConditionalTriggerType).
Conditional bool `json:"conditional,omitempty"`
// FreeAttributes is true when attribute names here are chosen by the
// config author rather than fixed by the parser, so an unknown name is
// not an error.
FreeAttributes bool `json:"freeAttributes,omitempty"`
Attributes []*SchemaAttr `json:"attributes"`
Blocks map[string]*SchemaNestedBlock `json:"blocks"`
Constraints []Constraint `json:"constraints"`
}
SchemaBody describes the contents of one block body: a plain block, one variant of a typed block, or a nested sub-block.
type SchemaContext ¶ added in v0.45.0
type SchemaContext struct {
Summary string `json:"summary,omitempty"`
Doc string `json:"doc,omitempty"`
// Fields are the shape's own fields first, then the universal ones every
// `ctx` carries.
Fields []*SchemaContextField `json:"fields"`
// OpenFields is true when Fields is a floor rather than the whole list: a
// site may carry more, named by its attribute's `contextFields`. Treat an
// unlisted field as unknown-but-possible rather than as an error.
OpenFields bool `json:"openFields,omitempty"`
}
SchemaContext describes one `ctx` shape, named by an attribute's `context`.
type SchemaContextField ¶ added in v0.45.0
type SchemaContextField struct {
Name string `json:"name"`
Type string `json:"type"`
Summary string `json:"summary,omitempty"`
Doc string `json:"doc,omitempty"`
// Optional is true when the field is absent from some evaluations.
Optional bool `json:"optional,omitempty"`
// Universal is true for a field every `ctx` carries whatever the site, so
// a consumer can group or fold them away.
Universal bool `json:"universal,omitempty"`
}
SchemaContextField describes one field readable as `ctx.<name>`.
type SchemaDocument ¶ added in v0.45.0
type SchemaDocument struct {
// SchemaVersion is the version of the output format itself.
SchemaVersion string `json:"schemaVersion"`
// VinculumVersion is the version of the binary that produced the document.
VinculumVersion string `json:"vinculumVersion"`
// Contexts maps a `ctx` shape name to its description. An attribute's
// `context` field names one of these.
Contexts map[string]*SchemaContext `json:"contexts"`
// Namespaces maps a top-level name in the evaluation namespace to its
// description: what `sys.`, `env.`, and `bus.` mean and what may follow
// them. Where `contexts` says what an expression sees at a particular site,
// this says what every expression sees everywhere.
Namespaces map[string]*SchemaNamespace `json:"namespaces"`
// Plugins lists the registry entries plugins contributed to this document,
// e.g. "client.acme". Absent when no plugins were loaded, so its presence
// is what tells a consumer the document describes more than a stock binary.
// The generator does not load plugins itself; the caller sets this.
Plugins []string `json:"plugins,omitempty"`
// Blocks maps top-level block type name to its description.
Blocks map[string]*SchemaBlock `json:"blocks"`
}
SchemaDocument is the root of the `vinculum schema` JSON output.
func GenerateSchema ¶ added in v0.45.0
func GenerateSchema(opts SchemaGenOptions) (*SchemaDocument, []error)
GenerateSchema describes the entire block language: every top-level block from blockSchema and from vinitSchema, every variant of a typed block from the registry that drives its parsing, and the curated metadata registered alongside them.
It reflects the in-tree registries as populated by init(), so it describes a stock binary; plugins are not loaded. Curation problems are always returned; opts.Strict decides whether the caller treats them as fatal.
func (*SchemaDocument) FilterByFile ¶ added in v0.45.0
func (d *SchemaDocument) FilterByFile(kind FileKind) *SchemaDocument
FilterByFile returns a copy of the document describing one of the two languages: the blocks of that file kind, the `ctx` shapes those blocks actually name, and the namespaces an expression in such a file may start from. A consumer that reads one kind of file wants exactly that, and a document carrying shapes nothing in it can name describes the generator rather than the language.
The receiver is not modified, and neither are the bodies: the copy shares them, since nothing downstream of generation mutates a described body. Filtering is deliberately not part of generation — validation walks the whole document, and a partial one would report every context of the language that was filtered out as described-but-unnamed.
type SchemaGenOptions ¶ added in v0.45.0
type SchemaGenOptions struct {
// Strict makes curation problems (metadata referencing an attribute or
// block that does not exist) fatal for the caller. Problems are always
// collected; Strict only decides whether they fail the command.
Strict bool
// RequireDocs additionally reports every block, variant, nested block, and
// attribute that carries no Summary.
RequireDocs bool
}
SchemaGenOptions controls schema generation.
type SchemaMember ¶ added in v0.45.0
type SchemaMember struct {
Name string `json:"name"`
// Type is the coarse value type: the attribute vocabulary plus `object`,
// `capsule`, and — for a capsule registered under a name usable in a `.cty`
// annotation — that name, e.g. `time`.
Type string `json:"type"`
// Value is the member's literal value, present only in a namespace whose
// values are the same in every process.
Value string `json:"value,omitempty"`
Summary string `json:"summary,omitempty"`
Doc string `json:"doc,omitempty"`
// FreeMembers is true for an object member whose own member names are not
// fixed by the language, such as the host's signal table.
FreeMembers bool `json:"freeMembers,omitempty"`
// Members are this member's own members, when it is an object.
Members []*SchemaMember `json:"members,omitempty"`
}
SchemaMember describes one member of a namespace, read as `<namespace>.<name>`.
type SchemaNamespace ¶ added in v0.45.0
type SchemaNamespace struct {
// Kind is "provider" or "block".
Kind string `json:"kind"`
// Block names the top-level block type that publishes names here, for a
// block namespace.
Block string `json:"block,omitempty"`
Summary string `json:"summary,omitempty"`
Doc string `json:"doc,omitempty"`
// DocPage is the hand-written reference page for this namespace, relative
// to doc/.
DocPage string `json:"docPage,omitempty"`
// Undocumented is true when no curated schema was registered for the
// namespace, as for a block.
Undocumented bool `json:"undocumented,omitempty"`
// Constant is true when every member's value is the same in every process,
// which is what makes a member's `value` meaningful.
Constant bool `json:"constant,omitempty"`
// FreeMembers is true when the member names are not fixed by the language,
// so `members` is empty by design rather than by omission. A block
// namespace is always free: its names come from the config.
FreeMembers bool `json:"freeMembers,omitempty"`
// Members are the namespace's members, sorted by name.
Members []*SchemaMember `json:"members"`
}
SchemaNamespace describes one top-level name in the evaluation namespace.
type SchemaNestedBlock ¶ added in v0.45.0
type SchemaNestedBlock struct {
Labels []string `json:"labels"`
// Repeatable is true when the block may appear any number of times.
Repeatable bool `json:"repeatable"`
// Required is true when exactly one instance must be present.
Required bool `json:"required"`
SchemaBody
}
SchemaNestedBlock describes a sub-block: its header plus its body.
type SchemaProvider ¶ added in v0.45.0
type SchemaProvider interface {
Schema() TypeSchema
}
SchemaProvider is an optional interface a BlockHandler may implement to contribute its block's schema. Handlers that don't are emitted "undocumented", which lets the schema land block by block.
type ServerBlockHandler ¶
type ServerBlockHandler struct {
BlockHandlerBase
}
func NewServerBlockHandler ¶
func NewServerBlockHandler() *ServerBlockHandler
func (*ServerBlockHandler) GetBlockDependencyId ¶
func (h *ServerBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
func (*ServerBlockHandler) Process ¶
func (h *ServerBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
func (*ServerBlockHandler) Schema ¶ added in v0.45.0
func (h *ServerBlockHandler) Schema() TypeSchema
Schema describes the server block for `vinculum schema`. A typed block has no body of its own; each server type contributes its own via WithSchema.
type ServerDefinition ¶
type ServerProcessor ¶ added in v0.19.0
type ServerProcessor func(config *Config, block *hcl.Block, body hcl.Body) (Listener, hcl.Diagnostics)
ServerProcessor is a function that processes a server block and returns a Listener.
type SignalActionHandler ¶
type SignalActionHandler struct {
Ctx context.Context
Logger *zap.Logger
UserLogger *zap.Logger
SignalActions map[platform.Signal]hcl.Expression
SignalCtx map[platform.Signal]*hcl.EvalContext
SigChannel chan os.Signal
AddedStartable bool
TracerProvider trace.TracerProvider
// Files is the source file map for rendering a failing signal action against
// its own line, set from the Config during Build(). Nil for a handler not
// built that way (the diagnostic writer tolerates a nil map).
Files map[string]*hcl.File
}
func NewSignalActionHandler ¶
func NewSignalActionHandler(logger, userLogger *zap.Logger) *SignalActionHandler
func (*SignalActionHandler) Start ¶
func (sa *SignalActionHandler) Start() error
type SignalsDefinition ¶
type SignalsDefinition struct {
SigHup hcl.Expression `hcl:"SIGHUP,optional"`
SigInfo hcl.Expression `hcl:"SIGINFO,optional"`
SigUsr1 hcl.Expression `hcl:"SIGUSR1,optional"`
SigUsr2 hcl.Expression `hcl:"SIGUSR2,optional"`
Disabled bool `hcl:"disabled,optional"`
DefRange hcl.Range `hcl:",def_range"`
}
type Startable ¶
type Startable interface {
Start() error
}
func NewErrorlessStartable ¶
func NewErrorlessStartable(startable errorlessStartable) Startable
type Stoppable ¶ added in v0.16.0
type Stoppable interface {
Stop() error
}
Stoppable is implemented by components that need graceful shutdown. Stop is called in reverse-start order on SIGINT/SIGTERM.
type SubscriberSource ¶ added in v0.35.0
type SubscriberSource struct {
Subscriber hcl.Expression
Action hcl.Expression
Transforms hcl.Expression
QueueSize *int
}
SubscriberSource groups the four HCL attributes that together specify where a block delivers events: a destination (a named subscriber or an inline action) plus an optional transform pipeline and an optional async queue.
Every block that accepts this pattern should declare the four attributes on its own definition struct with these exact HCL names:
Subscriber hcl.Expression `hcl:"subscriber,optional"` Action hcl.Expression `hcl:"action,optional"` Transforms hcl.Expression `hcl:"transforms,optional"` QueueSize *int `hcl:"queue_size,optional"`
After decoding, populate a SubscriberSource from those fields and call Resolve to obtain the final bus.Subscriber.
Example VCL:
subscriber = bus.main // XOR
action = log_info(topic, msg)
transforms = [ jq(".payload") ] // optional
queue_size = 100 // optional — enables async queue
func (SubscriberSource) Resolve ¶ added in v0.35.0
func (s SubscriberSource) Resolve( config *Config, defRange hcl.Range, name string, tp trace.TracerProvider, ) (bus.Subscriber, hcl.Diagnostics)
Resolve produces the bus.Subscriber specified by the source. Wrappers are applied in order: action|subscriber → transforms → async queue. Exactly one of Subscriber or Action must be provided.
`name` is used as the AsyncQueueingSubscriber instrumentation name (tracer scope + span attribute). `tp` (if non-nil) is forwarded to the async queue so background processing emits new-root SpanKindConsumer spans linked to the caller's span (vinculum-bus v0.13.0+).
type SubscriptionBlockHandler ¶
type SubscriptionBlockHandler struct {
BlockHandlerBase
}
func NewSubscriptionBlockHandler ¶
func NewSubscriptionBlockHandler() *SubscriptionBlockHandler
func (*SubscriptionBlockHandler) GetBlockDependencies ¶ added in v0.12.0
func (h *SubscriptionBlockHandler) GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
func (*SubscriptionBlockHandler) GetBlockDependencyId ¶
func (h *SubscriptionBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
func (*SubscriptionBlockHandler) Process ¶
func (h *SubscriptionBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
func (*SubscriptionBlockHandler) Schema ¶ added in v0.45.0
func (h *SubscriptionBlockHandler) Schema() TypeSchema
Schema describes the subscription block for `vinculum schema`.
type SubscriptionDefinition ¶
type SubscriptionDefinition struct {
Name string `hcl:"name,label"`
TargetExpr hcl.Expression `hcl:"target,optional"`
Topics []string `hcl:"topics"`
QueueSize *int `hcl:"queue_size,optional"`
Transforms hcl.Expression `hcl:"transforms,optional"`
Subscriber hcl.Expression `hcl:"subscriber,optional"`
ActionExpr hcl.Expression `hcl:"action,optional"`
Disabled bool `hcl:"disabled,optional"`
}
type TLSConfig ¶ added in v0.16.0
type TLSConfig struct {
Enabled bool `hcl:"enabled,optional"`
CACert string `hcl:"ca_cert,optional"`
Cert string `hcl:"cert,optional"`
Key string `hcl:"key,optional"`
InsecureSkipVerify bool `hcl:"insecure_skip_verify,optional"`
RequireClientCert bool `hcl:"require_client_cert,optional"`
SelfSigned bool `hcl:"self_signed,optional"`
DefRange hcl.Range `hcl:",def_range"`
}
TLSConfig holds TLS configuration for client or server connections. It is designed to be embedded in any block that needs TLS and decoded by gohcl.
For clients:
tls {
enabled = true
ca_cert = "/etc/certs/ca.crt" # verify server cert
cert = "/etc/certs/client.crt" # optional, for mTLS
key = "/etc/certs/client.key" # optional, for mTLS
insecure_skip_verify = false
}
For servers:
tls {
enabled = true
cert = "/etc/certs/server.crt"
key = "/etc/certs/server.key"
ca_cert = "/etc/certs/ca.crt" # optional, require client certs
require_client_cert = true # optional, enforce mTLS
}
func (*TLSConfig) BuildTLSClientConfig ¶ added in v0.16.0
BuildTLSClientConfig constructs a *tls.Config for use as a TLS client. Returns nil if Enabled is false. Relative paths are resolved against baseDir.
ca_cert sets the trusted CA pool (verifies the server certificate). cert + key provide a client certificate for mTLS. insecure_skip_verify disables server certificate verification.
func (*TLSConfig) BuildTLSServerConfig ¶ added in v0.16.0
BuildTLSServerConfig constructs a *tls.Config for use as a TLS server. Returns nil if Enabled is false. Relative paths are resolved against baseDir.
cert + key are required (the server's certificate). ca_cert sets the CA pool used to verify client certificates. require_client_cert enables mTLS (RequireAndVerifyClientCert).
type TriggerBlockHandler ¶ added in v0.17.0
type TriggerBlockHandler struct {
BlockHandlerBase
// contains filtered or unexported fields
}
TriggerBlockHandler processes trigger blocks. A fresh instance is created per Build() call; its registry is populated during FinishPreprocessing.
func NewTriggerBlockHandler ¶ added in v0.17.0
func NewTriggerBlockHandler() *TriggerBlockHandler
func (*TriggerBlockHandler) FinishPreprocessing ¶ added in v0.21.0
func (h *TriggerBlockHandler) FinishPreprocessing(config *Config) hcl.Diagnostics
FinishPreprocessing builds the per-build trigger registry by merging unconditional types with any conditional types whose features are enabled.
func (*TriggerBlockHandler) GetBlockDependencies ¶ added in v0.33.0
func (h *TriggerBlockHandler) GetBlockDependencies(block *hcl.Block) ([]string, hcl.Diagnostics)
func (*TriggerBlockHandler) GetBlockDependencyId ¶ added in v0.17.0
func (h *TriggerBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
GetBlockDependencyId returns "trigger.<name>" for trigger types that produce a cty value, enabling correct dependency ordering for blocks that reference trigger.<name>. Other trigger types return "" (no ordering needed). Falls back to the global (unconditional) registry when called before FinishPreprocessing.
func (*TriggerBlockHandler) Process ¶ added in v0.17.0
func (h *TriggerBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
func (*TriggerBlockHandler) Schema ¶ added in v0.45.0
func (h *TriggerBlockHandler) Schema() TypeSchema
type TriggerDefinition ¶ added in v0.17.0
type TriggerDefinition struct {
Type string `hcl:"type,label"`
Name string `hcl:"name,label"`
Disabled bool `hcl:"disabled,optional"`
Tracing hcl.Expression `hcl:"tracing,optional"`
DefRange hcl.Range `hcl:",def_range"`
RemainingBody hcl.Body `hcl:",remain"`
// TracerProvider is resolved from Tracing (or auto-wired) during Process()
// and is available to trigger-type processors via triggerDef.TracerProvider.
TracerProvider trace.TracerProvider
}
type TriggerProcessor ¶ added in v0.19.0
type TriggerProcessor func(config *Config, block *hcl.Block, def *TriggerDefinition) hcl.Diagnostics
TriggerProcessor is a function that processes a trigger block.
type TriggerRegistration ¶ added in v0.19.0
type TriggerRegistration struct {
Process TriggerProcessor
HasDependencyId bool // true if this trigger type produces a cty value at trigger.<name>
}
TriggerRegistration holds the processor and metadata for a trigger type.
type TypeSchema ¶ added in v0.45.0
type TypeSchema struct {
// Sample is a zero value (normally a pointer to one) of the gohcl decode
// struct for this body. Required for top-level blocks and typed variants;
// ignored for nested sub-blocks, whose structure is reflected from the
// parent's field type.
Sample any
// AlsoSamples lists further decode structs whose attributes and blocks
// belong to the same body. Some bodies are decoded in more than one pass —
// a sql client's dialect struct captures the rest with `,remain` and hands
// it to a second struct holding the dialect-agnostic settings — and the
// schema has to describe the union.
AlsoSamples []any
// Summary is a one-line description, used as a completion item's detail.
Summary string
// Doc is richer Markdown used for hover; may be multi-paragraph.
Doc string
// DocPage names the hand-written reference page for this type, relative to
// doc/ — "client-mqtt.md", or "server-vws.md#client-vws" for a type
// documented in a section of another page.
//
// It exists because a generated index has to link somewhere, and a link
// target synthesized by convention is exactly the kind of thing that rots
// silently: the page gets renamed and the index still points at it. A test
// checks that every DocPage names a file that exists and, for a fragment,
// a heading that is in it.
//
// Required for a variant of a typed block under --require-docs; those are
// what the generated per-type indexes link to.
DocPage string
// Attrs holds curated per-attribute metadata, keyed by HCL attribute name.
// Every key must name an attribute that reflection found.
Attrs map[string]AttrMeta
// FreeAttributes marks a body whose attribute names are chosen by the
// config author rather than fixed by the parser (`const`, an fsm
// `storage` block). Consumers should not flag an unknown attribute here.
FreeAttributes bool
// Blocks holds curated metadata for nested sub-blocks, keyed by HCL block
// type name. Structure is normally reflected and this only adds docs, so
// every key must name a sub-block reflection found — unless the entry
// carries its own Sample, which declares a sub-block of a body the parent
// parses by hand from a `,remain` body (see fsm's state/event/storage).
Blocks map[string]TypeSchema
// Repeatable and Required describe the header of a sub-block declared via
// its own Sample. For a reflected sub-block the field type already says
// whether the block is a slice, a pointer, or a value, so curating either
// is a reported problem — with one exception.
//
// Required is curatable on a *repeatable* sub-block, where it raises `0..n`
// to `1..n`. A slice cannot tell "any number, including none" apart from
// "one or more", so a parser that demands one (a `git` block with no
// `fetch` clones nothing) has no other way to say so. Together the two
// booleans read as they always have: required to appear, repeatable to
// appear again.
Repeatable bool
Required bool
// Variants declares the variant bodies of a typed block whose variants are
// not driven by a registry (currently only `metric`). Registry-driven
// blocks (client, server, trigger, condition, wire_format, editor) leave
// this nil; their variants come from the registry.
Variants map[string]TypeSchema
// Constraints are advisory cross-attribute rules that reflection cannot
// express. Every attribute they name must exist in the reflected body.
Constraints []Constraint
}
TypeSchema carries everything the `vinculum schema` command needs about one block body: a plain top-level block, one variant of a typed block, or a nested sub-block.
Sample drives structural reflection; everything else is curated by hand and validated against the reflected structure so it cannot silently drift. TypeSchema values are declared next to the decode struct they describe.
type VariableBlockHandler ¶ added in v0.11.0
type VariableBlockHandler struct {
BlockHandlerBase
// contains filtered or unexported fields
}
func NewVariableBlockHandler ¶ added in v0.11.0
func NewVariableBlockHandler() *VariableBlockHandler
func (*VariableBlockHandler) FinishPreprocessing ¶ added in v0.11.0
func (h *VariableBlockHandler) FinishPreprocessing(config *Config) hcl.Diagnostics
func (*VariableBlockHandler) GetBlockDependencyId ¶ added in v0.11.0
func (h *VariableBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
func (*VariableBlockHandler) Preprocess ¶ added in v0.11.0
func (h *VariableBlockHandler) Preprocess(block *hcl.Block) hcl.Diagnostics
func (*VariableBlockHandler) Process ¶ added in v0.11.0
func (h *VariableBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
func (*VariableBlockHandler) Schema ¶ added in v0.45.0
func (h *VariableBlockHandler) Schema() TypeSchema
Schema describes the var block for `vinculum schema`.
type VinculumPluginInitFunc ¶ added in v0.37.0
type VinculumPluginInitFunc = func(*PluginContext) hcl.Diagnostics
VinculumPluginInitFunc is the required signature of the entry point that every Go plugin must export under the name VinculumPluginInit. Returning a non-empty error diagnostics value aborts startup.
type WireFormatBlockHandler ¶ added in v0.30.0
type WireFormatBlockHandler struct {
BlockHandlerBase
}
WireFormatBlockHandler implements BlockHandler for wire_format blocks.
func NewWireFormatBlockHandler ¶ added in v0.30.0
func NewWireFormatBlockHandler() *WireFormatBlockHandler
func (*WireFormatBlockHandler) GetBlockDependencyId ¶ added in v0.30.0
func (h *WireFormatBlockHandler) GetBlockDependencyId(block *hcl.Block) (string, hcl.Diagnostics)
func (*WireFormatBlockHandler) Process ¶ added in v0.30.0
func (h *WireFormatBlockHandler) Process(config *Config, block *hcl.Block) hcl.Diagnostics
func (*WireFormatBlockHandler) Schema ¶ added in v0.45.0
func (h *WireFormatBlockHandler) Schema() TypeSchema
type WireFormatDefinition ¶ added in v0.30.0
type WireFormatDefinition struct {
Type string `hcl:"type,label"`
Name string `hcl:"name,label"`
DefRange hcl.Range `hcl:",def_range"`
RemainingBody hcl.Body `hcl:",remain"`
}
WireFormatDefinition is the common HCL structure for wire_format blocks.
type WireFormatProcessor ¶ added in v0.30.0
type WireFormatProcessor func(config *Config, block *hcl.Block, body hcl.Body) (cty.Value, hcl.Diagnostics)
WireFormatProcessor processes a wire_format block of a given type and returns a cty.Value to expose in the evaluation context. The value is typically a capsule wrapping a wire.WireFormat, but may also be an object with multiple capsule attributes (e.g. a protobuf plugin returning one capsule per message type).
Source Files
¶
- ambient.go
- assert.go
- auth.go
- baggagefilter.go
- blocks.go
- bus.go
- client.go
- condition.go
- config.go
- const.go
- decodehook.go
- dep.go
- editor.go
- exprcheck.go
- fsm.go
- funcdoc.go
- funcplugins.go
- functy.go
- functyerror.go
- git.go
- gitfetch.go
- gitmaterialize.go
- helptopics.go
- metrics.go
- namespace.go
- otlp.go
- parse.go
- pathutil.go
- plugin.go
- plugin_common.go
- procedure.go
- reactive.go
- reflect.go
- schema.go
- server.go
- signals.go
- subs.go
- tls.go
- transformplugin.go
- transforms.go
- trigger.go
- typelabel.go
- userfunc.go
- util.go
- variable.go
- vinit.go
- wireformat.go
- wireformat_block.go