routingrules

package
v0.22.12 Latest Latest
Warning

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

Go to latest
Published: Sep 25, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrUnbound = fmt.Errorf("routingrules: the authored runtime is not wired on this node, so a routing rule cannot be armed here. " +
	"Arming happens on a node that runs the authored-construct scheduler")

ErrUnbound is what a caller gets on a node that cannot arm anything. It is its own value so a handler can tell "this node cannot" apart from "this form is wrong", which are read by different people.

Functions

func Bind

func Bind(engine Engine, deps func() memql.AuthoredRuntimeDeps, shipped ShippedNames)

Bind installs the activation seam. Called once from app wiring, after the authored registry and scheduler exist.

func BoundSince

func BoundSince() time.Time

BoundSince reports when the seam was wired, for a status surface. The zero time means never.

func ConstructNameFor

func ConstructNameFor(f Form) string

ConstructNameFor is the name the generated construct carries. It is the form's own name: a rule is addressed by name in the registry, in the decision record and on the operator's screen, and a derived name would make those three disagree.

func GenerateRule

func GenerateRule(f Form) (string, error)

GenerateRule renders the construct. It assumes Validate passed; the one thing it re-checks is the name, because rendering an empty one produces text the parser refuses with a message about a missing identifier.

func Validate

func Validate(f Form, shipped ShippedNames) error

Validate refuses a form the DSL would refuse, in the operator's vocabulary and before anything is written.

It duplicates checks the parser also makes, and that duplication is the point: the parser's message is about a construct the operator never wrote, at a line number in a file that does not exist. This one is about the field they filled in.

Types

type Activator

type Activator struct {
	// contains filtered or unexported fields
}

Activator arms and retires routing rules.

func Bound

func Bound() *Activator

Bound returns an Activator, or nil on a node where nothing was bound.

func NewActivator

func NewActivator(engine Engine, deps func() memql.AuthoredRuntimeDeps, shipped ShippedNames) *Activator

NewActivator returns nil without an engine or without the authored runtime, so a caller can construct it unconditionally and a node that cannot arm anything installs nothing. A nil Activator's methods refuse with a sentence naming the missing half rather than panicking.

func (*Activator) Activate

func (a *Activator) Activate(ctx context.Context, owner string, f Form) (Result, error)

Activate renders the form, runs Gate 1, writes the rows and arms it.

func (*Activator) Retire

func (a *Activator) Retire(ctx context.Context, owner, name string) (Result, error)

Retire tears a rule's construct down.

type Engine

type Engine interface {
	Execute(ctx context.Context, query string) (*memql.ExecuteResult, error)
	ActivateApprovedBundle(ctx context.Context, owner, bundleId string, deps memql.AuthoredRuntimeDeps) (memql.ActivationResult, error)
	RetireActiveBundle(ctx context.Context, owner, bundleId string, deps memql.AuthoredRuntimeDeps) error
}

Engine is the narrow surface arming needs. An interface rather than the concrete engine so this package is testable without a database, and so the dependency reads as three named operations instead of "everything".

type EngineShippedNames

type EngineShippedNames struct{ Engine *memql.MemQLEngine }

EngineShippedNames reads the live registries.

func (EngineShippedNames) HasPolicy

func (e EngineShippedNames) HasPolicy(name string) bool

func (EngineShippedNames) HasRule

func (e EngineShippedNames) HasRule(name string) bool

type Form

type Form struct {
	// Name is the rule's construct name. It must not be a shipped name; the
	// authoring pipeline's core-first resolver refuses that, and Validate
	// refuses it earlier so the operator hears it from the form.
	Name string
	// Description becomes the /// doc comment, which is what a reader of the
	// rules list sees.
	Description string

	// When is the condition set, keyed by the closed @when keys. A key present
	// with an empty value is a condition matching only an empty value; a key
	// ABSENT is no condition at all. The map preserves that distinction, which
	// a struct of strings could not.
	When map[string]string

	// Policy is required.
	Policy string
	// Level optionally overrides the call's declared level.
	Level string
	// Precedence orders the rule. A tie with another unlocked rule refuses at
	// load, so the form carries the number rather than inventing one.
	Precedence int
	// OnUnavailable is "degrade" or "park". Empty renders nothing and reads as
	// degrade, matching the DSL's own default.
	OnUnavailable string
	// Excludes removes concrete models from this rule's resolution.
	Excludes []string
}

Form is what the OS sends and what the builtin takes. It is the rule as a person filled it in, and deliberately NOT the generated half -- no bundle id, no construct name, no last error. A generator that read its own past output would produce a construct whose content depended on it.

type Result

type Result struct {
	Name          string   `json:"name"`
	BundleId      string   `json:"bundleId"`
	Status        string   `json:"status"`
	Source        string   `json:"source"`
	Diagnostics   []string `json:"diagnostics,omitempty"`
	Error         string   `json:"error,omitempty"`
	ConstructName string   `json:"constructName"`
}

Result is what the builtin returns to the caller.

func Activate

func Activate(ctx context.Context, owner string, f Form) (Result, error)

Activate is the package-level entry point the integration calls.

func Retire

func Retire(ctx context.Context, owner, name string) (Result, error)

Retire is the package-level counterpart.

type ShippedNames

type ShippedNames = memql.ShippedNames

ShippedNames answers "is this name the embedded tree's".

It is an ALIAS rather than a second declaration of the same two methods. Go would satisfy both structurally, so a duplicate would work and would be a second name for one contract -- and the moment either grew a method the other would not, the compiler would report it at the call site rather than where the divergence was introduced.

Jump to

Keyboard shortcuts

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