store

package
v1.74.2 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Overview

Package store builds the storage ports once, from configuration, for the apps to be handed: the one place that knows which adapter backs them.

Everything else names the interfaces of internal/port. The adapter is chosen by the `ports.adapter` key of the configuration file: `legacy` (the default, today's ConfigMaps, Secrets and Valkey, unchanged), `memory` or `dynamodb`.

Index

Constants

View Source
const (
	AdapterLegacy = "legacy"
	AdapterMemory = "memory"
	// AdapterDynamoDB keeps State, the session index and the trigger in one
	// DynamoDB table.
	AdapterDynamoDB = "dynamodb"
)

The adapters `ports.adapter` names.

View Source
const BlobS3 = "s3"

BlobS3 is the adapter `ports.blob.adapter` names. It replaces one port and composes with any `ports.adapter`.

Variables

View Source
var ErrLocalLease = errors.New("the tick leases are held in this process only, so a running controller " +
	"would not be kept off the same target and both could act on it (duplicate invites or removals): " +
	"this is safe once a shared State exists (docs/decisions/0029, B3). Scale the controller to 0 and " +
	"pass --unsafe-local-lease to run the tick anyway")

ErrLocalLease is the refusal of a one-shot tick whose lease would not exclude the running controller.

Functions

func RequireSharedLease

func RequireSharedLease(shared, unsafeLocal bool) error

RequireSharedLease refuses a one-shot tick when its lease State is not shared with the controller's, unless the operator opted in.

Types

type Backend added in v1.58.0

type Backend = legacy.Backend

Backend is today's storage as it was opened.

type Config

type Config struct {
	Adapter string
	// Release prefixes the objects' names and the Valkey keys.
	Release string
	Kube    KubeNeed
	// Blob replaces the port of the same name; nil keeps what Adapter brings.
	Blob *config.PortsBlob
	// DynamoDB is the table of the `dynamodb` adapter.
	DynamoDB dynamoport.Config

	// Secrets delivers the secrets the document names (the Valkey password):
	// the composition root sets it after FromServe. Nil delivers none.
	Secrets secrets.Source
	// SecretsRoot is the serve document's `secrets.root` when its source is
	// ssm: the root the `ssm` Secrets adapter takes.
	SecretsRoot string
	// SecretsKMSKey is the serve document's `secrets.kmsKeyId` when its source
	// is ssm: the key the `ssm` Secrets adapter encrypts what it writes with.
	SecretsKMSKey string
	// Secrets layout (ADR 0041): the serve document's `secrets.layout`,
	// `.region`, `.endpoint` and `.grace` when its source is ssm. The layout
	// is v3 (the default) unless it is "transition" or "v4"; those put the
	// Secrets port over layout v4 (internal/secretstore).
	SecretsLayout   string
	SecretsRegion   string
	SecretsEndpoint string
	SecretsGrace    time.Duration
	// OpenState opens the backend of the v4 stores (storage/state/ssm over the
	// service's retryer, openSSMState).
	// Nil is that backend.
	OpenState secretstore.Opener

	// Cloudflare and Instance are the service document's `cloudflare` section
	// and the instance name; the Blob mints its own R2 credentials from a
	// preset of it (`ports.blob.s3.credentials.preset`). Nil when the blob uses
	// a static document, which needs neither.
	Cloudflare *config.Cloudflare
	Instance   string
	// CloudflareDial opens a Cloudflare account; nil is the real client.
	CloudflareDial minter.Dialer

	// Converted is a document converted from v1: an `ssm` secrets adapter
	// that names no root keeps v1's layout, /sluis.
	Converted bool
	// contains filtered or unexported fields
}

Config is what Open needs.

func FromRoster

func FromRoster(f *config.Roster) Config

FromRoster reads what the two controllers share. A controller's reports and links are objects in its namespace, so it requires the cluster.

func FromServe

func FromServe(f *config.Serve) (Config, error)

FromServe reads the configuration of `sluis serve`.

func (*Config) SetSecrets added in v1.74.0

func (c *Config) SetSecrets(s *config.Secrets)

SetSecrets carries the service document's `secrets` section (the `ssm` source: root, KMS key, layout, region, endpoint, grace) into the config. A controller assembled from the service document calls it too, so it sees the same layout the service does. Any other source sets nothing.

type KubeNeed

type KubeNeed int

KubeNeed says how much a process needs the namespace's objects.

const (
	// KubeNone opens nothing: a hub with `store: memory`.
	KubeNone KubeNeed = iota
	// KubeOptional tries, and goes on without when this is not a cluster: an
	// issuer proving recovery against one it may not be running in.
	KubeOptional
	// KubeRequired stops the start when this is not a cluster.
	KubeRequired
)

How much a process needs the cluster.

type Stores

type Stores struct {
	// Ports is every port, over the chosen adapter.
	Ports port.Set
	// Backend is today's storage as it was opened: what the `legacy` adapter
	// is made of, and, with any adapter, the cluster's own objects that stay the
	// cluster's (the token review, the declared OAuth client). The domain stores
	// (a connected workspace and its credential, an organisation, a person's
	// link, the Slack records) are on Ports for every adapter but `legacy`
	// (internal/portstore), and in the ConfigMaps and Secrets this reaches for
	// `legacy`. It is nil with the memory adapter, which has none.
	Backend *Backend
	// Adapter is the state adapter's name.
	Adapter string
	// Plan is the resolved adapter per concern, for the packages that wire a
	// concern this package does not.
	Plan port.Table
	// Secrets delivers the secrets the document names, by name: what the
	// composition root put in Config.Secrets. Nil delivers none.
	Secrets secrets.Source
	// V4 is the installation's secrets on layout v4: Internal and External
	// over one state store. Nil on layout v3, the default.
	V4 *secretstore.Stores
	// Shared is true when the state is one every replica sees: a Valkey.
	Shared bool
	// Usable is whether the State, Index and snapshot Blob ports work at all:
	// the memory adapter, and the legacy one with a Valkey. Without them a
	// caller keeps its own process-local store, as it always has.
	Usable bool
	// contains filtered or unexported fields
}

Stores is the ports, built once.

func Open

func Open(ctx context.Context, cfg Config, log *slog.Logger) (*Stores, error)

Open builds the ports for the adapter the configuration names.

func (*Stores) Close

func (s *Stores) Close()

Close releases what Open opened.

func (*Stores) LeaseState

func (s *Stores) LeaseState() (state port.State, shared bool)

LeaseState is the State the controllers take their tick leases from, and whether it is shared by every replica. A lease is only exclusive across processes when the State is: the legacy adapter keeps leases in Valkey, so without one a controller holds its leases in its own memory and a second replica would not be kept off (docs/concepts/sluis/ports.md, "The legacy adapter").

func (*Stores) Name

func (s *Stores) Name() string

Name says where state lives, for a log line and the console's page.

func (*Stores) Readiness

func (s *Stores) Readiness() any

Readiness is what readiness should ask: the Valkey, or nothing.

Jump to

Keyboard shortcuts

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