sqlengine

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Nov 8, 2026 License: Apache-2.0 Imports: 44 Imported by: 0

Documentation

Overview

Package sqlengine shares bounded evaluation, recovery and content authority across the SQLite and PostgreSQL public engine entry points.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RestoreBackup

func RestoreBackup(ctx context.Context, source, destination, contentDir, fencePath string, key []byte, hostDirectory ...string) error

RestoreBackup restores into a fresh SQLite destination, never overwriting a running dataset. fence is the independent current ledger, not a ledger from inside the backup. A retired snapshot is refused before any data is served.

func RestorePostgres

func RestorePostgres(ctx context.Context, source, dsn, destinationFence, contentDir, currentFence string, key []byte, hostDirectory ...string) error

func ValidateDisplayName

func ValidateDisplayName(name string) error

ValidateDisplayName accepts a name for a dataset. The name is host-supplied and shown to people, so it must be text: control characters would let a name rewrite a terminal or a log line it is printed into.

Types

type Store

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

func Open

func Open(ctx context.Context, path string, limits p.Limits) (result *Store, err error)

Open creates or reopens one dataset. Existing databases retain their identity, version secret and limits; supplied limits apply only when first created.

func OpenPostgres

func OpenPostgres(ctx context.Context, dsn, fencePath string, limits p.Limits) (result *Store, err error)

OpenPostgres opens a database this process shares with any other process opening it. Each holds a session advisory lock under its own executor identity, and a claim records the executor that made it, so a process can tell another's work in flight from work whose executor is gone without consulting a clock. fencePath must remain on durable storage independently of database backups.

func (*Store) Backup

func (s *Store) Backup(ctx context.Context, path string, key []byte, hostFiles ...string) error

Backup writes an authenticated encrypted snapshot. The key and independent retirement ledger must be retained separately. Existing output is never replaced.

func (*Store) BackupCaptured

func (s *Store) BackupCaptured(ctx context.Context, path string, key []byte, freeze func() func(), hostFiles ...string) (string, error)

BackupCaptured also returns the opaque S label authenticated inside the archive.

func (*Store) BackupCapturedWithFiles

func (s *Store) BackupCapturedWithFiles(ctx context.Context, path string, key []byte, freeze func() func(), files func() []string) (string, error)

BackupCapturedWithFiles resolves optional host files while their owner is frozen.

func (*Store) BackupConsistent

func (s *Store) BackupConsistent(ctx context.Context, path string, key []byte, freeze func() func(), hostFiles ...string) error

BackupConsistent is Backup for a host whose files describe the same state as the SQL: an account registry whose grants the SQL access rows carry. freeze stops the host changing them and returns what lets it continue. The SQL snapshot is pinned and the host files are read while it holds, so the archive cannot pair a registry from one moment with grants from another — which, restored, could give a token more than the live server did when the backup was taken. It holds only for the pin and the read, not the export.

func (*Store) BeginPage

func (s *Store) BeginPage(ctx context.Context, a store.Access, dataset, typeID string, q p.Query, size int) (store.PageStart, error)

BeginPage starts a page sequence. Where the query can be continued — every row, in identity order or in a sort the storage orders — it computes the first page alone and leaves the next pending, so starting costs one page rather than the whole result; see NextPage. Otherwise it takes the snapshot it always did.

func (*Store) CaptureRetirementEvidence

func (s *Store) CaptureRetirementEvidence(ctx context.Context) ([]byte, string, error)

CaptureRetirementEvidence captures all SQL retirements at one database snapshot plus independently retained historical evidence. It never relies on journaled flags, timestamps or a maintenance pass. The result is the supported restore fence format, including the valid empty fence. The label identifies R only.

func (*Store) CheckpointCleanup

func (s *Store) CheckpointCleanup(ctx context.Context) error

CheckpointCleanup retries physical page reclamation. Logical access was already revoked by Erase. Backups must use the restore fence, not raw copying.

func (*Store) CleanupContent

func (s *Store) CleanupContent(ctx context.Context) error

CleanupContent retries deletion and reclaims idle staging. Private files are named only with server-generated upload IDs, never caller-provided paths.

func (*Store) Close

func (s *Store) Close() error

func (*Store) ContentControl

func (s *Store) ContentControl(ctx context.Context, a store.Access, action, storeID, id string, body json.RawMessage) (any, error)

func (*Store) ContentTransfer

func (s *Store) ContentTransfer(ctx context.Context, token, method, rangeHeader string, body io.Reader) (store.ContentRead, error)

func (*Store) CreateDataset

func (s *Store) CreateDataset(ctx context.Context, a store.Access, displayName string, limits p.Limits, types []p.Meta, key string, digest [32]byte) (made store.Created, failure error)

CreateDataset provisions a dataset in this storage and makes the caller its administrator, which is the same policy Erase applies to a replacement: the authorization that asked for it is the only one provisioned, and any further grant is installed by the host.

Creating a dataset is composition, like installing a grant. It is deliberately not a protocol operation: the contract describes datasets a server already holds and says nothing about how one comes to exist.

Bounds are the dataset's own from here on. Passing the zero value takes the storage's, which is what a host with nothing particular to say should do.

A non-empty key retains the outcome under store.ServerScope so a caller whose response was lost can ask what happened instead of guessing. The receipt is recorded as an identity outcome, which is what it is: the answer a caller needs back is which dataset now exists, and an identity outcome is the one category a replay returns without a grant over the dataset it names — which matters here because the dataset did not exist when the key was claimed.

func (*Store) DatasetLimits

func (s *Store) DatasetLimits(ctx context.Context, dataset string) (p.Limits, error)

DatasetLimits reads one dataset's stored limits, for an operator changing them. It takes no access: it is composition, like Provisioned.

func (*Store) DatasetUsage

func (s *Store) DatasetUsage(ctx context.Context, dataset string) (store.Usage, error)

DatasetUsage measures one dataset. Composition only, like DatasetLimits.

func (*Store) Datasets

func (s *Store) Datasets(ctx context.Context, a store.Access) ([]store.Info, error)

Datasets lists every dataset in this storage that the caller holds a grant on, in identity order. A dataset the caller may not use is absent rather than refused, so the listing reports nothing about what else is here. An empty listing is not an error, and neither is an invalid access.

func (*Store) EnableContent

func (s *Store) EnableContent(ctx context.Context, directory string) error

EnableContent binds a private filesystem byte store to the SQL authority. Call during composition, before publishing the store to concurrent callers.

func (*Store) EnableReads

func (s *Store) EnableReads(names ...string) error

EnableReads advertises optional read capabilities for every transaction this store evaluates. Call it during composition, before serving requests.

func (*Store) EndPage

func (s *Store) EndPage(ctx context.Context, a store.Access, dataset, cursor string) error

func (*Store) Erase

func (s *Store) Erase(ctx context.Context, a store.Access, dataset, confirm string) (store.EraseResult, error)

func (*Store) Info

func (s *Store) Info(ctx context.Context, a store.Access, dataset string) (store.Info, error)

The named dataset is checked by the evaluator restored from the image, which carries that image's identity. Deciding it here as well would leave one of the two decisions unexercised, and the two could drift apart.

func (*Store) Mutate

func (s *Store) Mutate(ctx context.Context, a store.Access, m store.Mutation) (store.Reply, error)

func (*Store) MutateWith

func (s *Store) MutateWith(ctx context.Context, a store.Access, m store.Mutation, host func(store.Tx, *sql.Tx) error) (store.Reply, error)

MutateWith composes protocol writes, host rows/events and receipt outcome in one SQL transaction. A durable claim is committed before this callback starts. The callback has the same ownership restrictions as WithTx and is never called for a replay. The request digest must also identify the host's requested work.

func (*Store) NextPage

func (s *Store) NextPage(ctx context.Context, a store.Access, dataset, cursor string) (json.RawMessage, error)

func (*Store) PreviewErase

func (s *Store) PreviewErase(ctx context.Context, a store.Access, dataset string) (store.ErasePreview, error)

func (*Store) Provisioned

func (s *Store) Provisioned(ctx context.Context) ([]store.Dataset, error)

Provisioned names every dataset in this storage, for composition only.

It takes no access, which is the point: this is the call that names the dataset a first grant is installed on, and no grant could name it. The composition owns the storage, so enumerating it is not a disclosure. Nothing routes a request here — what a caller may see is Datasets.

func (*Store) PruneReceipts

func (s *Store) PruneReceipts(ctx context.Context) error

PruneReceipts discards only terminal outcomes older than the advertised window measured from claim time. An unresolved claim is never discarded.

The window is each dataset's own, because that is the one its description advertises. Taking the storage's would let a dataset promising a long window lose an outcome early, which a caller asking for its status would read as never having happened.

func (*Store) Reach

func (s *Store) Reach(ctx context.Context, a store.Access) ([]string, error)

Reach names the datasets one authorization holds access on, which is not the dataset its approval named: creating a dataset installs access to it for the caller that created it.

func (*Store) Read

func (s *Store) Read(ctx context.Context, a store.Access, dataset string, fn func(store.Tx) error) error

Read evaluates a request that reads and may scan. It no longer loads the dataset: records are fetched by identity or streamed by type as the request needs them, so a query for ten rows reads about ten rows.

Only reads. A write computes what changed by comparing the image before and after, so an image missing records would describe their absence as a deletion — which is why the write path still loads everything, and why that is a separate change rather than part of this one.

func (*Store) ReadRecord

func (s *Store) ReadRecord(ctx context.Context, a store.Access, dataset string, fn func(store.Tx) error) error

ReadRecord fetches the records it is asked for and no others, so reading one record costs one record rather than the dataset holding it.

func (*Store) ReadSchema

func (s *Store) ReadSchema(ctx context.Context, a store.Access, dataset string, fn func(store.Tx) error) error

Read evaluates a request that changes nothing. It takes no writer's turn, runs on the read pool in a read-only transaction, and never diffs or saves the state it built — three things a read was paying for and using none of.

The image it builds is still the whole dataset; narrowing that is a separate change. What this removes is the writer's lock, the defensive copy the evaluator makes so a failed write can be dropped, and the second copy taken afterwards to compare against. ReadSchema answers from the types alone. The objects are not fetched or decoded, which is the whole of the saving: describing one type used to cost reading every record in the dataset.

func (*Store) ReaderCut

func (s *Store) ReaderCut(ctx context.Context, dataset string) (uint64, error)

ReaderCut captures the next mint in the dataset's own serialized sequence. A later write can proceed before grants are installed, but its identities are already beyond the cut and cannot enter the frozen view.

func (*Store) RecoverCreation

func (s *Store) RecoverCreation(ctx context.Context, a store.Access, key string, digest [32]byte) (store.Created, bool, error)

RecoverCreation answers from a retained claim and never makes one, so a caller may be answered before any gate on new work is applied.

func (*Store) RecoveryLimits

func (s *Store) RecoveryLimits() p.Limits

RecoveryLimits bounds a request body before any dataset is known, so it is the storage's declared bound rather than any one dataset's. What a dataset actually enforces is on its own row and in its own description.

func (*Store) RegisterHostRegistry

func (s *Store) RegisterHostRegistry(ctx context.Context) error

RegisterHostRegistry marks a reference-server file registry owner for its lifetime. Call during composition, before any registry/grant reconciliation. Multiple owners may serve, but none can capture all their independent files.

func (*Store) RenameDataset

func (s *Store) RenameDataset(ctx context.Context, dataset, displayName string) error

RenameDataset changes a dataset's display name. A name is a label for people and says nothing about identity, which is why this is allowed at all: the dataset identity a client holds is unchanged.

func (*Store) Replay

func (s *Store) Replay(ctx context.Context, a store.Access, dataset, key string, digest [32]byte) (store.Reply, bool, error)

func (*Store) ResolveAbandonedClaims

func (s *Store) ResolveAbandonedClaims(ctx context.Context) error

ResolveAbandonedClaims fails the claims of executors that are no longer running, and leaves alone the claims of executors that are.

An executor holds its own session lock for as long as it lives, taken before it can have made any claim. Another process asks whether an executor is gone by trying to take that lock: if it succeeds the executor's session ended, and a session ends only when the process does. Nothing here consults a clock, because a slow executor and a dead one look the same to one, and guessing wrong resolves live work as failed.

An empty executor is a claim made before executors were recorded. Startup proves no process of that kind is running before it calls this.

Two processes may reach the same executor at once; only one takes the lock, and the other tries again on its next sweep.

func (*Store) Revoke

func (s *Store) Revoke(ctx context.Context, dataset string, a store.Access) error

func (*Store) ServerRetentionSeconds

func (s *Store) ServerRetentionSeconds() int

ServerRetentionSeconds is the floor for receipts belonging to no dataset. It is separate from the storage's dataset window on purpose: raising that one to reach this would also lengthen every created dataset's own write receipts, because a creation takes the storage's limits when the request carries none.

func (*Store) SetAuthorization

func (s *Store) SetAuthorization(ctx context.Context, dataset string, a store.Access, g store.Authorization) error

func (*Store) SetContentCleanupDirectory

func (s *Store) SetContentCleanupDirectory(directory string) error

SetContentCleanupDirectory keeps deletion obligations live when the content capability is disabled. Call only during host composition.

func (*Store) SetDatasetLimits

func (s *Store) SetDatasetLimits(ctx context.Context, dataset string, limits p.Limits) error

SetDatasetLimits replaces one dataset's limits.

This is what makes 507 dataset_full an answer an operator can act on: the bound a dataset outgrew is stored on it at creation, and without this there was no way to raise it short of recreating the dataset.

Every bound may move either way except the retention window, which may only grow. A client was promised it and reconciles against it; shortening it would void outcomes clients are still entitled to ask about.

func (*Store) SoleDataset

func (s *Store) SoleDataset(ctx context.Context) (store.Dataset, error)

SoleDataset names the one dataset a storage holds, for a composition built around exactly one. It refuses rather than choosing when there are several, because picking one arbitrarily is how a deployment ends up administering a dataset nobody meant.

func (*Store) StartMaintenance

func (s *Store) StartMaintenance(ctx context.Context)

StartMaintenance owns periodic cleanup. Call once during host composition; Close cancels and joins it before closing SQL connections.

func (*Store) Status

func (s *Store) Status(ctx context.Context, a store.Access, dataset, key string) (store.Receipt, error)

func (*Store) Transact

func (s *Store) Transact(ctx context.Context, a store.Access, dataset string, fn func(store.Tx) error) error

func (*Store) WithTx

func (s *Store) WithTx(ctx context.Context, a store.Access, dataset string, fn func(store.Tx, *sql.Tx) error) error

WithTx commits core records and host SQL together. The SQL transaction belongs to this store: callers must not commit, roll back, retain, or concurrently use it. A callback must perform no network I/O and must return every operation error.

fn may run twice. A write is first evaluated against only the records it touches; one that needs the whole dataset is rolled back to a savepoint — the host's SQL with it — and fn runs again from the complete image. So fn must keep nothing outside itself that a second run would add to.

Jump to

Keyboard shortcuts

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