sql

package
v0.13.0 Latest Latest
Warning

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

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

Documentation

Overview

Package sql is the SQL provider (ADR-0232, FEAT-0011): the SQLDatabase reconciler, which deploys one rqlite engine per database through the add-on runtime with durable storage (ADR-0231), the engine password, the in-process registry of Ready engines, and the engine client. Imported as sqlsvc.

Index

Constants

View Source
const (
	ReasonEngineNotReady       = "EngineNotReady"
	ReasonEngineConvergeFailed = "EngineConvergeFailed"
	ReasonNoDirectory          = "NoDirectory"
	ReasonRestored             = "Restored"
)

The Ready reasons a SQLDatabase reports when False, and the reasons of DataMissing.

View Source
const DefaultCallTimeout = 30 * time.Second

DefaultCallTimeout bounds one SQL call when sql.callTimeout is unset (ADR-0233 Decision 4).

View Source
const (
	Runtime = "rqlite"
)

The engine's fixed shape (ADR-0232 Decisions 2 and 3).

Variables

This section is empty.

Functions

func ChangeToken

func ChangeToken(master []byte, ns v1.NamespaceName, name v1.ObjectName) string

ChangeToken is a database's change feed capability (ADR-0235 Decision 2): HMAC-SHA256 of the node master over "funcd-sql-cdc/<ns>/<name>", base64url. Nothing stores it.

func EnginePassword

func EnginePassword(master []byte, ns v1.NamespaceName, name v1.ObjectName) string

EnginePassword derives a database's engine password from the node master (ADR-0232 Decision 5): HMAC-SHA256 over "funcd-sql-engine/<ns>/<name>", base64url. Nothing stores it; a master rotation changes it at the next engine start.

Types

type Backups

type Backups struct {
	Engines *Engines
	Master  []byte
	Client  *http.Client // nil ⇒ a node client with no timeout, bounded by each call's context; share one
}

Backups copies and loads databases through their engines for workload backups (ADR-0234): Source is workload.Sources.SQL, and Backups implements the backup service's SQLLoader. Neither holds a whole database in memory.

func (Backups) Empty

func (b Backups) Empty(ctx context.Context, ns v1.NamespaceName, name v1.ObjectName) error

Empty leaves a database with no table, view, index or trigger, by loading an empty SQLite file through /db/load.

func (Backups) HasTables

func (b Backups) HasTables(ctx context.Context, ns v1.NamespaceName, name v1.ObjectName) (bool, error)

HasTables reports whether a database holds a table, view, index or trigger, the restore's emptiness rule.

func (Backups) Load

func (b Backups) Load(ctx context.Context, ns v1.NamespaceName, name v1.ObjectName, file io.Reader) error

Load replaces all of a database's data with the SQLite file read from file: Empty, then the file streamed to rqlite's /boot. /db/load was killed for its memory near 100 MB under the default 256Mi bound, where /boot stays near 12 MiB (rqlite 10.5.3, checked 2026-10-12), so this is ADR-0234 Decision 3's switch.

func (Backups) Source

func (b Backups) Source(ctx context.Context, ns v1.NamespaceName, name v1.ObjectName) (io.ReadCloser, error)

Source streams a database's SQLite file in DELETE mode, one self-contained file (ADR-0234 Decision 2). Its reader fails, instead of reaching io.EOF, when the engine sets the stream-error trailer.

type Engines

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

Engines is the in-process registry of Ready engines' addresses (ADR-0232 Decision 6), filled by the reconciler and read by the deletion probe and the access facade. Safe for concurrent use.

func NewEngines

func NewEngines() *Engines

NewEngines returns an empty registry.

func (*Engines) Address

func (e *Engines) Address(ns v1.NamespaceName, name v1.ObjectName) (string, bool)

Address returns a Ready engine's address.

func (*Engines) Delete

func (e *Engines) Delete(ns v1.NamespaceName, name v1.ObjectName)

Delete forgets an engine that is not Ready or is deleted.

func (*Engines) Set

func (e *Engines) Set(ns v1.NamespaceName, name v1.ObjectName, addr string)

Set records a Ready engine's address.

type Facade

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

Facade resolves a caller's alias, asks Cedar, and calls the database's engine as user funcd. It implements local.SQL and health.ReadChecker.

func NewFacade

func NewFacade(d FacadeDeps) (*Facade, error)

NewFacade builds the facade; Resolver, Authorizer, Engines and Master are required.

func (*Facade) CheckRead

func (f *Facade) CheckRead(ctx context.Context, ns v1.NamespaceName, fn v1.ObjectName, alias string) error

CheckRead resolves the alias, asks sql::read and checks that the engine is Ready, with no engine call: the dependency check of a binding (ADR-0233 Decision 8). A missing engine wraps local.ErrEngineNotReady.

func (*Facade) Execute

func (f *Facade) Execute(ctx context.Context, ns v1.NamespaceName, fn v1.ObjectName, binding string, stmts []json.RawMessage) ([]local.ExecResult, error)

Execute runs statements in one transaction on /db/execute (ADR-0233): sql::read and sql::write, since RETURNING reads; one failed statement applies none.

func (*Facade) Query

func (f *Facade) Query(ctx context.Context, ns v1.NamespaceName, fn v1.ObjectName, binding string, stmts []json.RawMessage) ([]local.QueryResult, error)

Query runs read-only statements on /db/query (ADR-0233): sql::read, and a write is refused by the engine.

type FacadeDeps

type FacadeDeps struct {
	Resolver    Resolver
	Authorizer  auth.Authorizer
	Engines     *Engines
	Master      []byte
	HTTPClient  *http.Client  // nil ⇒ a node client bounded by CallTimeout
	CallTimeout time.Duration // 0 ⇒ DefaultCallTimeout
	Logger      *slog.Logger
}

FacadeDeps configures the SQL facade, the PEP of every context.sql call (ADR-0233 Decision 4).

type Feed

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

Feed receives the changes every engine posts and turns those an EventSource names into named CloudEvents (ADR-0235). It reads the databases and EventSources from the store on each delivery, so it holds no registry; its boot gate stays closed until Loaded, so no change is published before the Sensors that act on it subscribe.

func NewFeed

func NewFeed(d FeedDeps) (*Feed, error)

NewFeed builds the change feed.

func (*Feed) Handler

func (f *Feed) Handler() http.Handler

Handler is POST /v1/changes/{token}. The path, which carries the token, is never logged.

func (*Feed) Loaded

func (f *Feed) Loaded()

Loaded opens the boot gate: the Sensors present at the start have subscribed, so an event the feed publishes reaches them. Until then every delivery with a valid token answers 503 and rqlite retries it.

func (*Feed) Serve

func (f *Feed) Serve(ctx context.Context, host string, port int) error

Serve listens on host:port, retrying each second until the address exists (the bridge appears with the first worker), and serves the feed until ctx is done.

func (*Feed) URL

func (f *Feed) URL(host string, port int) func(ns v1.NamespaceName, name v1.ObjectName) string

URL is the endpoint a database's engine posts its changes to, on host:port.

type FeedDeps

type FeedDeps struct {
	Store         store.Store
	Publisher     eventing.Publisher
	Watermarks    Watermarks
	Master        []byte
	Hold          hold.Gate          // nil ⇒ never held
	NamespaceHold hold.NamespaceGate // nil ⇒ no namespace held
	Logger        *slog.Logger
}

FeedDeps configures the change feed; Store, Publisher, Watermarks and Master are required.

type MetaReader

type MetaReader interface {
	Get(ctx context.Context, gvk v1.GroupVersionKind, ns v1.NamespaceName, name v1.ObjectName) (v1.Object, error)
}

MetaReader is the read-only metastore view the resolver needs.

type Prober

type Prober struct {
	Engines *Engines
	Master  []byte
	Volumes provider.Volumes
	Client  *http.Client // nil ⇒ a node client with a 5 s timeout
}

Prober answers the deletion protection's question (ADR-0232 Decision 7): does a database's engine hold a user table?

func (Prober) HasTables

func (p Prober) HasTables(ctx context.Context, ns v1.NamespaceName, name v1.ObjectName) (bool, error)

HasTables reports whether the engine holds a user table. With no Ready engine it answers false when the database has no directory (nothing was ever written) and fails Unavailable when it has one (fail closed).

type Reconciler

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

Reconciler is the controller.Reconciler for KindSQLDatabase.

func NewReconciler

func NewReconciler(d ReconcilerDeps) (*Reconciler, error)

NewReconciler builds the reconciler. Store, Provider, Engines and Master are required, and Provider must implement provider.Volumes, else Invalid.

func (*Reconciler) Backups

func (r *Reconciler) Backups() Backups

Backups copies and loads databases over this reconciler's engines, for workload backups (ADR-0234).

func (*Reconciler) Engines

func (r *Reconciler) Engines() *Engines

Engines is the registry of Ready engines the reconciler fills.

func (*Reconciler) MapFunction

func (r *Reconciler) MapFunction(ctx context.Context, obj v1.Object) []controller.Request

MapFunction maps a Function change to the databases of its namespace, whose binding counts it may change.

func (*Reconciler) MapRestore

func (r *Reconciler) MapRestore(_ context.Context, obj v1.Object) []controller.Request

MapRestore maps a Restore to the databases it loads, whose DataMissing it may clear.

func (*Reconciler) Orphans

func (r *Reconciler) Orphans(ctx context.Context) ([]v1.ObjectRef, error)

Orphans returns the engines whose directory has no SQLDatabase, for hold status (ADR-0232 Decision 7).

func (*Reconciler) Prober

func (r *Reconciler) Prober() Prober

Prober answers the deletion protection over this reconciler's engines and storage.

func (*Reconciler) ReclaimOrphans

func (r *Reconciler) ReclaimOrphans(ctx context.Context) error

ReclaimOrphans removes, before the controller runs, the directory of every engine with no SQLDatabase left; a no-op while the platform is held, whose hold status lists them instead.

func (*Reconciler) Reconcile

func (r *Reconciler) Reconcile(ctx context.Context, req controller.Request) (controller.Result, error)

Reconcile converges one SQLDatabase: deleted ⇒ tear the engine down and reclaim its directory unless held; else converge its engine, record a Ready engine's address, and write the status only when it changed.

type ReconcilerDeps

type ReconcilerDeps struct {
	Store             store.Store
	Provider          provider.Runtime // OwnerKind SQLDatabase; must implement provider.Volumes
	Engines           *Engines
	Master            []byte
	ImageFor          func(runtime string) string
	Hold              hold.Gate // nil ⇒ never held
	Logger            *slog.Logger
	SupervisionPeriod time.Duration
	// ChangeFeedURL is the endpoint each engine posts its changes to (ADR-0235 Decision 1); nil ⇒ no change feed.
	ChangeFeedURL func(ns v1.NamespaceName, name v1.ObjectName) string
	// Watermarks are the change feed's, dropped with a deleted database; nil ⇒ none.
	Watermarks Watermarks
	// DurableStorage is engine storage that outlives a daemon start: only then does a missing directory mean lost
	// data (DataMissing). False with no storage root or with storage.mode memory.
	DurableStorage bool
}

ReconcilerDeps configures the SQLDatabase reconciler (ADR-0232).

type Resolver

type Resolver interface {
	Resolve(ctx context.Context, ns v1.NamespaceName, fn v1.ObjectName, alias string) (v1.ObjectName, error)
}

Resolver maps a caller's alias to the database its spec.sql binds (ADR-0233 Decision 4). The binding is the read grant, so a missing alias is Forbidden.

func NewResolver

func NewResolver(r MetaReader) (Resolver, error)

NewResolver builds the metastore-backed Resolver.

type Watermarks

type Watermarks interface {
	Get(ctx context.Context, ns v1.NamespaceName, database v1.ObjectName, epoch string) (uint64, error)
	Set(ctx context.Context, ns v1.NamespaceName, database v1.ObjectName, epoch string, index uint64) error
	Delete(ctx context.Context, ns v1.NamespaceName, database v1.ObjectName) error
}

Watermarks keeps, per database and engine epoch, the highest Raft index whose events were published (ADR-0235 Decision 3); the event store's ChangeWatermarks implements it.

Directories

Path Synopsis
Package engineargs builds the rqlited command line and auth file for a SQL database's engine (ADR-0232 Decision 4), shared by the container entrypoint (cmd/funcd-rqlite) and the funcdctl dev engine (ADR-0237 Decision 2) so the two cannot drift.
Package engineargs builds the rqlited command line and auth file for a SQL database's engine (ADR-0232 Decision 4), shared by the container entrypoint (cmd/funcd-rqlite) and the funcdctl dev engine (ADR-0237 Decision 2) so the two cannot drift.

Jump to

Keyboard shortcuts

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