Help us shape the future of Go! Take the 2026 Go Developer Survey

app

package
v0.29.31 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2026 License: Apache-2.0 Imports: 137 Imported by: 0

Documentation

Overview

Package app implements the phased bootstrap for the MemQL service. It separates the monolithic mustCreateDependencies into clearly scoped phases: config, database, engine, integrations, transport, and cluster.

Build tags control which phases run for each node type binary:

go build .                  → standalone (all phases, all code)
go build -tags cognition .  → cognition binary
go build -tags agent .      → agent binary
go build -tags planner .    → planner binary
go build -tags bff .        → bff binary

The Build() function is defined in build_*.go files gated by build tags.

Index

Constants

View Source
const DefaultRunShutdownTimeout = 30 * time.Second

DefaultRunShutdownTimeout caps how long Run gives the dependency graph to drain on shutdown. Matches the value memql/main.go used pre-#356 (the dependencyShutdownTimeout package const there); kept in the app package so consumers don't have to know about it unless they want to override.

View Source
const DefaultShutdownDrainDelay = 5 * time.Second

DefaultShutdownDrainDelay is how long Run keeps serving AFTER a shutdown signal before it begins the dependency Stop sweep (#552, graceful shutdown). The window lets k8s notice the pod is Terminating + the readiness probe flip to 503 (via BeginDrain) and remove this pod from the Service endpoints, so NEW traffic stops arriving while in-flight requests finish -- instead of new connections racing onto a pod that's tearing down. terminationGracePeriodSeconds in the manifests must exceed this plus the grace period plus the Stop budget. Override via the carrier binary (MEMQL_SHUTDOWN_DRAIN_DELAY).

View Source
const DefaultShutdownGracePeriod = 25 * time.Second

DefaultShutdownGracePeriod bounds how long Run waits, AFTER the drain delay (endpoint-removal window) has elapsed, for in-flight work to finish before it transitions the node Draining -> Stopped and runs the dependency Stop sweep (memql#1269, the graceful-drain BEHAVIOUR on top of the #1268 lifecycle seams). The node is de-routed (readiness 503, gossip DRAINING), but existing bidirectional streams can still submit work. This grace lets the in-flight user streams (server.ActiveStreams via RunConfig.ActiveWork) drain to zero so a rolling deploy doesn't drop a turn mid-flight. In-flight that outlives the grace is cut off at the deadline (the bounded #1119 GracefulStop in the Stop sweep then forces remaining streams closed). Override via the carrier binary (MEMQL_SHUTDOWN_GRACE_PERIOD). A zero value falls back to this default; a negative value skips the in-flight wait entirely.

View Source
const DefaultStartupReadyWarningInterval = 30 * time.Second

DefaultStartupReadyWarningInterval reports a slow dependency without treating elapsed time as readiness. A shutdown signal can cancel the wait; the platform's startup probe owns the maximum startup window.

View Source
const EnvApprovalSink = "MEMQL_SAFETY_APPROVAL_SINK"

EnvApprovalSink opts a node OUT of the approval sink (memql#232). Default is on (consult v1:work:approval rows whenever the engine is ready -- epic memql#4966 moved the sink off v1:safety:approvalRequest so every human gate shares one inbox). Recognised off values: "off" / "false" / "0" (case-insensitive, trimmed). When opted out, Ask verdicts in enforce mode fall back to the pre-approval "requires user approval" refusal -- shadow mode never reaches the Ask branch regardless.

View Source
const EnvPersistClassifications = "MEMQL_SAFETY_PERSIST_CLASSIFICATIONS"

EnvPersistClassifications opts a node OUT of persisting v1:safety:classification rows via insertSafetyClassification (memql#234). Default is on (persist whenever the engine is ready). Recognised off values: "off" / "false" / "0" (case-insensitive, trimmed).

View Source
const EnvSafetyLLMProvider = "MEMQL_SAFETY_LLM_PROVIDER"

EnvSafetyLLMProvider opts a node into the LLM semantic classifier (memql#230). When set + matched by a registered structured-chat AI provider, app boot includes the LLM layer in the chain. Unset (or unmatched) leaves the rules-only default -- the system runs in shadow mode end-to-end, the LLM classifier is opt-in per node.

Variables

This section is empty.

Functions

func ConvertExecuteResultToMap

func ConvertExecuteResultToMap(result *memql.ExecuteResult) map[string]any

ConvertExecuteResultToMap converts *memql.ExecuteResult to map[string]any so that the cognition integration can access it uniformly.

func DefaultStartDependencies

func DefaultStartDependencies(dependencies ...common.Dependency)

DefaultStartDependencies is the package default for RunConfig.Start. Calls dep.Start(context.Background()) in registration order; never errors (Start is expected to be best-effort + log internally).

Exported so callers can compose with their own start hooks (e.g. tests that count + delegate).

func DefaultStopDependencies

func DefaultStopDependencies(ctx context.Context, dependencies ...common.Dependency)

DefaultStopDependencies is the package default for RunConfig.Stop. Sorts by Order() descending (highest-order = top of the stack; stops first), then calls dep.Stop with the caller's ctx OR a fresh per-dep timeout context when the caller didn't provide a deadline.

Stable tie-break keeps deterministic shutdown order across runs (mainly for log readability + test pinning).

func DefaultWaitForDependenciesReady added in v0.15.0

func DefaultWaitForDependenciesReady(ctx context.Context, deps []common.Dependency) error

DefaultWaitForDependenciesReady waits for actual readiness, never for a timeout that impersonates success. Cancellation names the unfinished dependency.

func DefaultWaitForShutdownSignal

func DefaultWaitForShutdownSignal(ctx context.Context) os.Signal

DefaultWaitForShutdownSignal waits for an OS signal or context cancellation.

func Run

func Run(cfg RunConfig)

Run is the canonical lifecycle entry point for a memql carrier binary. Bundles Build + Start + EmitSystemStartup + WaitForSignal + EmitSystemShutdown + Stop into a single call so consumers (memql/main.go, the carrier repo's main.go) don't need to duplicate the 30+ lines of orchestration.

Returns nothing; failures during build call cfg.Overrides.FatalWithLogger which is expected to os.Exit. The shutdown path is best-effort: a hung dependency that exceeds its per-dep ShutdownTimeout context will still trigger the next dependency's Stop after its context fires. Run blocks until WaitForSignal returns + the Stop sweep completes.

memql#356: extracted from memql/main.go's main() body so the carrier repo's binary can share the same lifecycle without duplicating ~30 LOC. Pre-extraction shape preserved bit-exactly so the bff binary's runtime behaviour is identical.

Types

type App

type App struct {
	Logger       *slog.Logger
	Version      string
	Dependencies []common.Dependency
	// contains filtered or unexported fields
}

App holds the shared state accumulated across bootstrap phases.

func Build

func Build(serviceLogger *slog.Logger, version string, overrides Overrides) *App

Build constructs service dependencies for the default build (BFF). When no build tag is specified, the binary runs as a BFF node. BFF nodes serve domain-specific frontends.

func (*App) AuthoredRuntimeDeps added in v0.15.0

func (a *App) AuthoredRuntimeDeps() memql.AuthoredRuntimeDeps

AuthoredRuntimeDeps assembles the dependency bundle the activation path (engine.ActivateApprovedBundle) drives: the registry, the scheduler register / deregister hooks, the catalog promoter, and the audit sink. Exposed so the bundle-activation entry point (and tests) can build it from the live App.

func (*App) BeginNodeDrain added in v0.15.0

func (a *App) BeginNodeDrain()

BeginNodeDrain flips this node's lifecycle to Draining (memql#1268) -- the mechanism a graceful SIGTERM drain (memql#1269) and the operator trigger (memql#1270) drive. The graceful-drain BEHAVIOUR (finish in-flight work bounded by a grace period, then MarkNodeStopped + the dependency Stop sweep) is orchestrated by app.Run (memql#1269); the operator-triggered drain is memql#1270. Flipping to Draining advertises DRAINING in gossip (peers route around at once) and flips readiness to 503 (LB/k8s de-route) via the #1268 observer, while /livez stays 200. No-op on non-mesh binaries.

func (*App) BunDB added in v0.17.1

func (a *App) BunDB() *bun.DB

BunDB exposes the pooled database handle, for the operator subcommands that work at the ROW level rather than through the engine.

`memql backup export` is the case that needs it: a backup is every row in the cluster, in storage order, streamed at constant memory. The engine's query path is the wrong instrument for that -- it shapes and filters per concept and gates per row, which is exactly right for serving a caller and exactly wrong for taking a faithful copy. A backup that silently omitted rows the query layer chose not to return would be discovered only during a restore, which is the worst possible moment.

The authorization for this is the same one `pat mint` and `enrolment-token mint` rely on: somebody who can exec the binary inside the pod already holds the cluster's secrets. It is not reachable over any wire.

Nil until the database phase has run.

func (*App) DeployControlService added in v0.15.0

func (a *App) DeployControlService() any

DeployControlService exposes the deploy-control service wired during the identity integrations phase. Returned as `any` to keep component/deploycontrol out of non-identity builds' import graphs; the identity-tagged admin portal type-asserts back to *deploycontrol.Service for in-process calls. Nil on binaries built without -tags identity.

func (*App) EmitSystemShutdown

func (a *App) EmitSystemShutdown()

EmitSystemShutdown publishes the system.shutdown event.

func (*App) EmitSystemStartup

func (a *App) EmitSystemStartup()

func (*App) Engine

func (a *App) Engine() *memql.MemQLEngine

Engine exposes the MemQL engine wired during the engine-and-bus phase. Used by operator subcommands (mint, etc.) that bootstrap the App but don't bring up transport. Nil until engineAndBus() has run.

func (*App) IdentityService

func (a *App) IdentityService() any

IdentityService exposes the identity service wired during the identity integrations phase. Returned as `any` to keep component/identity out of non-identity builds' import graphs; the identity-tagged subcommand handler type-asserts back to *identity.Service. Nil on binaries built without -tags identity.

func (*App) MarkNodeReady added in v0.15.0

func (a *App) MarkNodeReady()

MarkNodeReady flips this node's lifecycle from Starting to Ready (memql#1268), advertised on the next gossip heartbeat and consulted by the readiness handler. Called from the Run lifecycle once every dependency has reported ready, before EmitSystemStartup. No-op on non-mesh binaries (no PeerManager / lifecycle). Idempotent.

func (*App) MarkNodeStopped added in v0.15.0

func (a *App) MarkNodeStopped()

MarkNodeStopped flips this node's lifecycle to the terminal Stopped state (memql#1268), advertised as STOPPED in gossip. Called by app.Run at the END of the graceful SIGTERM drain (memql#1269) -- after in-flight work has finished (or the grace deadline fired) and immediately before the dependency Stop sweep tears the transport down -- so the node leaves the mesh as cleanly Stopped rather than vanishing mid-Draining. Stopped is terminal and a no-op if already there; readiness already reports 503 from the Draining transition, so this does not change the readiness surface. No-op on non-mesh binaries.

func (*App) OperatorDrainReason added in v0.15.0

func (a *App) OperatorDrainReason() string

OperatorDrainReason returns the reason recorded by the operator drain trigger (empty if none was set). Used for shutdown log context.

func (*App) OperatorDrainSignal added in v0.15.0

func (a *App) OperatorDrainSignal() <-chan struct{}

OperatorDrainSignal returns the channel app.Run's wait path selects on (closed by RequestOperatorDrain). Nil on non-mesh binaries / nodes with no operator entrypoint, in which case Run waits on the OS signal only.

func (*App) RequestOperatorDrain added in v0.15.0

func (a *App) RequestOperatorDrain(reason string) bool

RequestOperatorDrain is the on-demand operator entrypoint into the graceful drain (memql#1270, epic memql#1259 decision #4: "a maintenance/Draining state triggered two ways from ONE mechanism -- automatically on deploy (SIGTERM) and on-demand by an operator command"). An owner/admin operator's gRPC NodeMaintenanceMsg lands in the handler, which calls this. It closes the opDrain channel exactly once; app.Run's wait path selects on that channel alongside the OS shutdown signal, so the operator trigger runs the IDENTICAL drain sequence #1269 runs on SIGTERM -- BeginNodeDrain (Draining advertised in gossip + readiness 503) -> drain delay -> in-flight wait bounded by MEMQL_SHUTDOWN_GRACE_PERIOD -> MarkNodeStopped -> dependency Stop sweep. There is no separate drain code path: the operator path is a second TRIGGER into the one mechanism.

Idempotent: a second call (or a SIGTERM that races it) is a no-op because the underlying drain is already under way. Returns true if THIS call initiated the drain, false if it was already requested. A nil opDrain (non-mesh binary, or a node that didn't bring the channel up) returns false -- such a node has no operator drain entrypoint and the handler reports it as unavailable rather than pretending to drain.

type AttachmentEngineAdapter

type AttachmentEngineAdapter struct {
	Engine *memql.MemQLEngine
}

AttachmentEngineAdapter wraps MemQLEngine to satisfy server.MemQLExecutor.

func (*AttachmentEngineAdapter) Execute

func (a *AttachmentEngineAdapter) Execute(ctx context.Context, query string) (any, error)

type AudioEngineAdapter

type AudioEngineAdapter struct {
	Engine *memql.MemQLEngine
}

AudioEngineAdapter wraps MemQLEngine to satisfy audiows.MemQLExecutor.

func (*AudioEngineAdapter) ExecuteInsert

func (a *AudioEngineAdapter) ExecuteInsert(ctx context.Context, query string) error

type CampaignsEngineAdapter added in v0.16.0

type CampaignsEngineAdapter struct {
	Engine *memql.MemQLEngine
}

CampaignsEngineAdapter wraps MemQLEngine to satisfy campaigns.Engine (memql#3348). Same (any, error) seam as the outbound and inbound adapters, for the same reason: the sending engine's tests fake flat row envelopes so suppression, resume and rate-limit behaviour are provable without a database, and MaterializeRows unwraps either form.

func (*CampaignsEngineAdapter) Execute added in v0.16.0

func (a *CampaignsEngineAdapter) Execute(ctx context.Context, query string) (any, error)

func (*CampaignsEngineAdapter) InvokeAIStructured added in v0.26.0

func (a *CampaignsEngineAdapter) InvokeAIStructured(ctx context.Context, templateID string, data map[string]any, schemaName string, schema json.RawMessage, strict bool) (string, error)

InvokeAIStructured keeps model routing and strict output validation at the engine seam.

func (*CampaignsEngineAdapter) OrganizationCapable added in v0.22.10

func (a *CampaignsEngineAdapter) OrganizationCapable(ctx context.Context, account, verb, resource string) bool

type CognitionEngineAdapter

type CognitionEngineAdapter struct {
	Engine *memql.MemQLEngine
}

CognitionEngineAdapter wraps MemQLEngine to satisfy cognition.MemQLEngine. The key difference: memql.MemQLEngine.Execute returns (*ExecuteResult, error) but cognition.MemQLEngine expects (any, error), so this adapter converts the result.

func (*CognitionEngineAdapter) AcknowledgeWorkGuidance added in v0.28.0

func (a *CognitionEngineAdapter) AcknowledgeWorkGuidance(ctx context.Context, ids []string) error

func (*CognitionEngineAdapter) CatalogNearMatches added in v0.15.0

func (a *CognitionEngineAdapter) CatalogNearMatches(ctx context.Context, matchText string, limit int) ([]memql.CatalogNearMatch, error)

CatalogNearMatches delegates to the engine's compose-first fuzzy retrieval (memql#957): embed a need's match text and rank the caller's cataloged constructs by cosine similarity. Used by the authoring design pass to decide reuse-vs-author. The adapter exists because CatalogNearMatches is a method on the concrete *MemQLEngine, which the planner's narrow Engine interface does not expose.

func (*CognitionEngineAdapter) CompactWorkContext added in v0.23.1

func (a *CognitionEngineAdapter) CompactWorkContext(ctx context.Context, messages []common.ChatMessage, tools []common.ToolDefinition, target int) ([]common.ChatMessage, error)

Shared context management for agent turns regardless of their UI surface.

func (*CognitionEngineAdapter) CompileBundle added in v0.15.0

func (a *CognitionEngineAdapter) CompileBundle(constructs []memql.SandboxConstruct) memql.SandboxReport

CompileBundle delegates to the engine's Gate-1 sandbox compile+bind harness (memql#956). Used by the planner authoring loop's emit/repair pass (#960) and the everyday-task capture orchestrator (#1161): it compiles + binds a candidate bundle's constructs in isolation (never the live engine Init path) and returns per-construct diagnostics. The adapter exists because SandboxCompileBundleWithEngine needs the concrete *MemQLEngine, which the planner's narrow Engine interface does not expose.

func (*CognitionEngineAdapter) ContextWithWorkCallDeadline added in v0.25.0

func (a *CognitionEngineAdapter) ContextWithWorkCallDeadline(ctx context.Context) (context.Context, context.CancelFunc, error)

func (*CognitionEngineAdapter) Execute

func (a *CognitionEngineAdapter) Execute(ctx context.Context, query string) (any, error)

func (*CognitionEngineAdapter) ExecuteToolByName

func (a *CognitionEngineAdapter) ExecuteToolByName(ctx context.Context, name string, args map[string]any) (string, error)

func (*CognitionEngineAdapter) InvokeAI added in v0.15.0

func (a *CognitionEngineAdapter) InvokeAI(ctx context.Context, templateId string, data map[string]any) (any, error)

func (*CognitionEngineAdapter) InvokeAIChatWithFilteredTools added in v0.15.0

func (a *CognitionEngineAdapter) InvokeAIChatWithFilteredTools(
	ctx context.Context,
	templateId string,
	data map[string]any,
	toolNames []string,
) (string, error)

InvokeAIChatWithFilteredTools delegates to the engine's bounded tool-calling loop, restricted to the named tool set. Used by the planner integration's trainSpecialist dispatcher to drive the Trainer Agent's web-search + chunk-write tool loop.

func (*CognitionEngineAdapter) InvokeAIStructured added in v0.15.0

func (a *CognitionEngineAdapter) InvokeAIStructured(
	ctx context.Context,
	templateId string,
	data map[string]any,
	schemaName string,
	schema json.RawMessage,
	strict bool,
) (string, error)

InvokeAIStructured delegates to the engine's structured-output path. Used by the cognition AI router, prediction analyzer, and any other "logic" prompt that wants provider-enforced JSON shape.

func (*CognitionEngineAdapter) PauseWorkForBudget added in v0.28.0

func (a *CognitionEngineAdapter) PauseWorkForBudget(ctx context.Context, ceiling *memql.RunCeilingError, messages []common.ChatMessage) error

func (*CognitionEngineAdapter) PrepareWorkTool added in v0.25.0

func (a *CognitionEngineAdapter) PrepareWorkTool(ctx context.Context) error

func (*CognitionEngineAdapter) ReadWorkGuidance added in v0.28.0

func (a *CognitionEngineAdapter) ReadWorkGuidance(ctx context.Context) ([]memql.WorkGuidance, error)

func (*CognitionEngineAdapter) RecordBundleValidation added in v0.26.0

func (a *CognitionEngineAdapter) RecordBundleValidation(ctx context.Context, v memql.BundleValidationInput) error

RecordBundleValidation hands the planner's Gate 1 verdicts to the engine's one recorder of them: recordBundleValidation is @serverOnly (memql#6022), and the planner does not stamp internal origin.

func (*CognitionEngineAdapter) RecoverWorkModelCall added in v0.28.0

func (a *CognitionEngineAdapter) RecoverWorkModelCall(ctx context.Context, failure string, attempt, maxRetries int, messages []common.ChatMessage) (bool, error)

func (*CognitionEngineAdapter) RegisterIntegration

func (a *CognitionEngineAdapter) RegisterIntegration(provider memql.IntegrationProvider) error

func (*CognitionEngineAdapter) RenderPrompt

func (a *CognitionEngineAdapter) RenderPrompt(templateId string, data map[string]any) (string, error)

func (*CognitionEngineAdapter) ResolveSkills

func (a *CognitionEngineAdapter) ResolveSkills(ctx context.Context, skillIds []string) (memql.SkillBundle, error)

func (*CognitionEngineAdapter) RestoreWorkContinuation added in v0.25.0

func (a *CognitionEngineAdapter) RestoreWorkContinuation(ctx context.Context, messages []common.ChatMessage) ([]common.ChatMessage, error)

func (*CognitionEngineAdapter) RunBundleDryRun added in v0.15.0

RunBundleDryRun delegates to the engine's Gate-2 behavioral dry-run entry point (memql#958). Used by the planner authoring loop's Gate-2 handoff (#960): it runs a Gate-1-clean bundle's automation under the tiered side-effect interception layer (reads real + metered, mutations isolated to an ephemeral sandbox partition, webhooks recorded-and-blocked) and returns the approval artifact. The adapter exists because RunBundleDryRun needs the concrete *MemQLEngine, which the planner's narrow Engine interface does not expose.

func (*CognitionEngineAdapter) SaveWorkContinuation added in v0.25.0

func (a *CognitionEngineAdapter) SaveWorkContinuation(ctx context.Context, messages []common.ChatMessage) error

func (*CognitionEngineAdapter) ToolCallee added in v0.22.0

func (a *CognitionEngineAdapter) ToolCallee(tool string) (kind, callee string, ok bool)

ToolCallee delegates to the engine's answer of how a tool's call is written as a statement (memql#5370). The planner's transcript capture writes each recorded tool call as the construct call its handler makes; the adapter exists because the tool registry is on the concrete *MemQLEngine.

func (*CognitionEngineAdapter) ToolDefinitionsForNames

func (a *CognitionEngineAdapter) ToolDefinitionsForNames(names []string) []common.ToolDefinition

func (*CognitionEngineAdapter) WorkCallFailure added in v0.25.0

func (a *CognitionEngineAdapter) WorkCallFailure(ctx context.Context) error

func (*CognitionEngineAdapter) WorkModelCallBudget added in v0.28.3

func (a *CognitionEngineAdapter) WorkModelCallBudget(ctx context.Context) (int, int, error)

func (*CognitionEngineAdapter) WriteAuthoredConstruct added in v0.26.0

func (a *CognitionEngineAdapter) WriteAuthoredConstruct(ctx context.Context, c memql.AuthoredConstructInput) error

WriteAuthoredConstruct hands the planner's member-construct writes to the engine's one writer of them: createAuthoringConstruct is @serverOnly (memql#6022), and the planner does not stamp internal origin.

func (*CognitionEngineAdapter) WriteAuthoringBundle added in v0.26.0

func (a *CognitionEngineAdapter) WriteAuthoringBundle(ctx context.Context, b memql.AuthoringBundleInput) error

WriteAuthoringBundle hands the planner's bundle creations to the engine's one writer of them: createAuthoringBundle is @serverOnly (memql#6022), and the planner does not stamp internal origin.

type EdgeEngineAdapter added in v0.18.0

type EdgeEngineAdapter struct {
	Engine *memql.MemQLEngine
}

EdgeEngineAdapter wraps MemQLEngine to satisfy edge.Engine (memql#3710). Same (any, error) seam as the outbound, inbound and campaigns adapters -- edge.NewEngineExecutor's own tests fake this narrow shape directly, and MaterializeRows unwraps either form.

func (*EdgeEngineAdapter) Execute added in v0.18.0

func (a *EdgeEngineAdapter) Execute(ctx context.Context, query string) (any, error)

type InboundEngineAdapter added in v0.15.0

type InboundEngineAdapter struct {
	Engine *memql.MemQLEngine
}

InboundEngineAdapter wraps MemQLEngine to satisfy inbound.Engine (memql#2957). Mirrors OutboundEngineAdapter: the receiver wants the (any, error) seam so its tests drive the staging call without a database.

func (*InboundEngineAdapter) Execute added in v0.15.0

func (a *InboundEngineAdapter) Execute(ctx context.Context, query string) (any, error)

type OutboundEngineAdapter added in v0.15.0

type OutboundEngineAdapter struct {
	Engine *memql.MemQLEngine
}

OutboundEngineAdapter wraps MemQLEngine to satisfy outbound.Engine (memql#2521). Same shape as CognitionEngineAdapter's Execute seam: the worker wants (any, error) so its tests can fake flat row envelopes; MaterializeRows unwraps either form.

func (*OutboundEngineAdapter) Execute added in v0.15.0

func (a *OutboundEngineAdapter) Execute(ctx context.Context, query string) (any, error)

type Overrides

type Overrides struct {
	NewDatabase       func(args ...database.DatabaseArg) (*memoryNodesDatabase.MemoryNodesDatabase, error)
	NewHTTPServer     func(args ...server.ServerArg) (*server.Server, error)
	NewEngine         func(db *bun.DB, args ...component.Arg) (*memql.MemQLEngine, error)
	FatalWithLogger   func(logger *slog.Logger, msg string, args ...any)
	LoadServiceEnvOpt func() (service.ServiceEnvOptions, error)
	// AssertUnauthenticatedSurface is the boot check that every route
	// reachable without auth middleware is declared (memql#2939). Injectable
	// so the wiring test can drive its error path without a mutable global or
	// an exported test mutator in the shipped binary.
	AssertUnauthenticatedSurface func(routes []string) error
	// AssertSelfAuthenticatedSurface is the boot check that every route granted
	// the third-tier verifier exemption is also certified as failing closed
	// (memql#3062). Injectable for the same reason as the field above.
	//
	// Unlike that one it runs on EVERY binary, because it compares two static
	// declarations rather than a binary's route table -- and because the hole
	// it guards opens on verifier-CONSUMING nodes, which is precisely where the
	// check above does not run.
	AssertSelfAuthenticatedSurface func() error
}

Overrides holds injectable factory functions for testing. When a field is nil, the real implementation is used.

type RunConfig

type RunConfig struct {
	// Logger is the root slog.Logger every component derives from.
	// Required.
	Logger *slog.Logger

	// Version is the service version string stamped onto startup
	// events + health probes. Required.
	Version string

	// Overrides bundles the injectable hooks the App needs at
	// build time (FatalWithLogger, LoadServiceEnvOpt). See
	// Overrides for the field-level contract.
	Overrides Overrides

	// ShutdownTimeout caps how long the per-dependency Stop calls
	// have to complete. Zero falls back to DefaultRunShutdownTimeout.
	// Tests pass a shorter value to keep the suite snappy.
	ShutdownTimeout time.Duration

	// BeginDrain is invoked the instant a shutdown signal arrives,
	// BEFORE the drain delay + Stop sweep (#552). The carrier binary
	// wires it to component/server.SetDraining(true) so /healthz starts
	// returning 503 and k8s/LB de-routes the pod. Zero = no-op (the
	// drain delay still applies). Kept as a hook so the app package
	// doesn't import component/server.
	BeginDrain func()

	// DrainDelay is how long to keep serving after the signal before
	// the in-flight wait + Stop sweep, giving endpoint removal time to
	// propagate. Zero falls back to DefaultShutdownDrainDelay; negative
	// disables the delay (tests pass a negative or tiny value).
	DrainDelay time.Duration

	// GracePeriod bounds the in-flight drain (memql#1269): after the
	// DrainDelay window, Run waits up to this long for ActiveWork to
	// report zero before transitioning Draining -> Stopped and running
	// the Stop sweep. Zero falls back to DefaultShutdownGracePeriod;
	// negative skips the in-flight wait (tests pass a tiny/negative
	// value). The carrier binary wires it from MEMQL_SHUTDOWN_GRACE_PERIOD.
	GracePeriod time.Duration

	// ActiveWork reports the count of currently in-flight units of work
	// (the carrier wires it to component/server.ActiveStreams -- open
	// user-facing MemqlService.Stream sessions). Run polls it during the
	// grace window and proceeds to teardown the instant it hits zero.
	// Zero (nil) means "no in-flight accounting" -- Run waits the full
	// grace period unless GracePeriod is negative. Kept as a hook so the
	// app package doesn't import component/server. (memql#1269)
	ActiveWork func() int64

	// WaitForReady blocks until dependencies are ready or ctx is cancelled.
	// Returning an error prevents Ready and system.startup, then drains the app.
	// Overrides must observe ctx so shutdown also works during startup.
	WaitForReady func(ctx context.Context, deps []common.Dependency) error

	// Start is the per-dependency start hook. Zero falls back to
	// the package default, which calls dep.Start(context.Background())
	// in registration order. Tests override to inject failures or
	// capture call order.
	Start func(deps ...common.Dependency)

	// Stop is the per-dependency stop hook. Zero falls back to the
	// package default, which sorts by Order() descending + stops
	// each with a per-dep ShutdownTimeout context. Tests override
	// to capture ordering or inject hangs.
	Stop func(ctx context.Context, deps ...common.Dependency)

	// WaitForSignal optionally replaces the OS signal source. It must return
	// when ctx is cancelled (with nil if no signal arrived), so an operator
	// drain or failed startup can release the waiter. Nil registers SIGINT and
	// SIGTERM synchronously before starting dependencies.
	WaitForSignal func(ctx context.Context) os.Signal

	// SetHealth is invoked with the live dependency slice after the
	// app builds. Zero is a no-op. The standalone helper that mints
	// the health-probe surface lives in component/server, but the
	// app package keeps it pluggable so callers without an HTTP
	// surface (subcommands, tests) don't need to drag the server
	// package into their import graph.
	SetHealth func(deps []common.Dependency)
}

RunConfig configures Run. Every field has a sensible default the app package supplies when omitted -- the only required fields in practice are Logger, Version, and Overrides.

Carrier-binary callers (memql/main.go + the carrier repo's main.go) populate Logger via mustCreateServiceLogger (binary-side helper) + Version via the binary's resolveServiceVersion. Subcommand dispatch + the `.env` override stay caller-side because they're binary-specific + run BEFORE the logger / overrides exist.

type ShopperEngineAdapter added in v0.22.9

type ShopperEngineAdapter struct {
	Engine *memql.MemQLEngine
}

ShopperEngineAdapter wraps MemQLEngine to satisfy server.MemQLExecutor for a pack's declared SHOPPER SURFACE (epic memql#5532, issue memql#5551).

ITS OWN ADAPTER RATHER THAN A SHARED ONE, matching every other consumer in this file, because the seam is where a future difference would land: this is the only executor in the tree reached by an unauthenticated member of the public, and a shared adapter would make narrowing it later a change to everybody's path.

func (*ShopperEngineAdapter) Execute added in v0.22.9

func (a *ShopperEngineAdapter) Execute(ctx context.Context, query string) (any, error)

Source Files

Jump to

Keyboard shortcuts

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