Documentation
¶
Overview ¶
Package database provisions database server instances (PostgreSQL, MySQL, MariaDB, Redis) as containers and manages the logical databases they host, so a single instance can back many apps instead of one container per database.
Index ¶
- Constants
- Variables
- func InstancePasswordSecretName(inst *models.DatabaseInstance) string
- func InstanceURLSecretName(inst *models.DatabaseInstance) string
- func PasswordSecretName(inst *models.DatabaseInstance, db *models.Database) string
- func URLSecretName(inst *models.DatabaseInstance, db *models.Database) string
- type AppController
- type AppDatabase
- type ConnectionInfo
- type DumpRef
- type EngineDefault
- type Enqueuer
- type ImageResolver
- type LiveStatus
- type LogicalBackup
- type NetworkProvider
- type NodeDocker
- type NodeGuard
- type OwnerExister
- type Placement
- type SecretWriter
- type ServerInfo
- type Service
- func (s *Service) AttachNetwork(ctx context.Context, workspaceID, instanceID, networkID uint) (*models.DatabaseInstance, error)
- func (s *Service) AttachToApp(workspaceID, dbID, appID uint, envPrefix string) (*models.Database, error)
- func (s *Service) CreateDatabase(ctx context.Context, workspaceID, instanceID uint, name string, appID *uint) (*models.Database, error)
- func (s *Service) DatabaseConnection(inst *models.DatabaseInstance, d *models.Database) (ConnectionInfo, error)
- func (s *Service) DatabaseConnectionForApp(workspaceID, appID, dbID uint) (ConnectionInfo, error)
- func (s *Service) Delete(ctx context.Context, inst *models.DatabaseInstance) error
- func (s *Service) DeleteDatabase(ctx context.Context, workspaceID, id uint) error
- func (s *Service) DetachFromApp(workspaceID, dbID uint) (*models.Database, error)
- func (s *Service) DetachNetwork(ctx context.Context, workspaceID, instanceID, networkID uint) (*models.DatabaseInstance, error)
- func (s *Service) EngineDefaults() []EngineDefault
- func (s *Service) FindDatabaseByDeclName(workspaceID uint, declName string) (*models.Database, *models.DatabaseInstance, bool)
- func (s *Service) FindReusableInstance(workspaceID uint, engine models.DBEngine) *models.DatabaseInstance
- func (s *Service) Get(workspaceID, id uint) (*models.DatabaseInstance, error)
- func (s *Service) GetDatabase(workspaceID, id uint) (*models.Database, error)
- func (s *Service) IDByUID(uid string) (uint, error)
- func (s *Service) InstanceConnection(inst *models.DatabaseInstance) (ConnectionInfo, error)
- func (s *Service) List(workspaceID uint) ([]models.DatabaseInstance, error)
- func (s *Service) ListByApp(workspaceID, appID uint) ([]AppDatabase, error)
- func (s *Service) ListDatabases(workspaceID, instanceID uint) ([]models.Database, error)
- func (s *Service) ListDatabasesByWorkspace(workspaceID uint) ([]models.Database, error)
- func (s *Service) LiveStatus(ctx context.Context, inst *models.DatabaseInstance) LiveStatus
- func (s *Service) MaybeRefreshSizes(inst *models.DatabaseInstance)
- func (s *Service) PlanUpgrade(workspaceID, instanceID uint, target string) (*UpgradePlan, error)
- func (s *Service) PrepareDatabase(workspaceID, instanceID uint, name string, appID *uint) (*models.Database, error)
- func (s *Service) Provision(ctx context.Context, workspaceID, serverID uint, name string, ...) (*models.DatabaseInstance, error)
- func (s *Service) RecreateDatabase(ctx context.Context, inst *models.DatabaseInstance, db *models.Database) error
- func (s *Service) Reencrypt(ctx context.Context, workspaceID uint) (int, error)
- func (s *Service) ResolveDependency(ctx context.Context, workspaceID, serverID, pinInstance uint, ...) (*models.DatabaseInstance, *models.Database, ConnectionInfo, bool, error)
- func (s *Service) Restart(ctx context.Context, inst *models.DatabaseInstance) error
- func (s *Service) RunProvision(ctx context.Context, instanceID uint) error
- func (s *Service) RunUpgradeJob(ctx context.Context, instanceID uint, target, path string, stopApps bool) error
- func (s *Service) SetAppController(a AppController)
- func (s *Service) SetEventBus(b *eventbus.Bus)
- func (s *Service) SetImageResolver(r ImageResolver)
- func (s *Service) SetLogicalBackup(b LogicalBackup)
- func (s *Service) SetNetworkProvider(p NetworkProvider)
- func (s *Service) SetNodeGuard(g NodeGuard)
- func (s *Service) SetOwner(workspaceID, id uint, kind string, ownerID uint, name string) error
- func (s *Service) SetOwnerExister(fn OwnerExister)
- func (s *Service) SetQuota(q *quota.Service)
- func (s *Service) SetSecrets(w SecretWriter)
- func (s *Service) SetServerInfo(si ServerInfo)
- func (s *Service) Start(ctx context.Context, inst *models.DatabaseInstance) error
- func (s *Service) Stop(ctx context.Context, inst *models.DatabaseInstance) error
- func (s *Service) StreamLogs(ctx context.Context, workspaceID, instanceID uint, follow bool, tail string, ...) error
- func (s *Service) StreamStatus(ctx context.Context, inst *models.DatabaseInstance, ...) error
- func (s *Service) StreamWorkspaceStatus(ctx context.Context, workspaceID uint, send func(eventbus.Event) error) error
- func (s *Service) SyncSizes(ctx context.Context, inst *models.DatabaseInstance) error
- func (s *Service) UniqueDatabaseName(instanceID uint, base string) (string, error)
- func (s *Service) Upgrade(ctx context.Context, workspaceID, instanceID uint, target string, ...) (*models.DatabaseInstance, error)
- func (s *Service) UpgradeOptions(workspaceID, instanceID uint) (*UpgradeOptions, error)
- type StatusEvent
- type UpgradeOptions
- type UpgradePlan
- type WorkspaceStatusEvent
Constants ¶
const ( SecretOwnerDatabase = "database" // a logical database (its scoped user) SecretOwnerInstance = "db_instance" // an instance (redis / admin) )
Owner kinds for a managed database's Vault secrets.
const ( PathInPlace = "in-place" // swap the image on the same data volume PathDumpRestore = "dump-restore" // dump all logical DBs and restore into a fresh volume )
Upgrade paths: how the data is carried from the old version to the new one.
Variables ¶
var ( ErrUnsupportedEngine = errors.New("unsupported database engine") ErrSlugTaken = errors.New("database name already taken in workspace") ErrNoLogicalDBs = errors.New("this engine does not support multiple databases") ErrInstanceNotReady = errors.New("database instance is not running yet") ErrNotFound = errors.New("not found") ErrNameTaken = errors.New("a database with this name already exists on the instance") ErrNoContainer = errors.New("database has no container; re-provision it") ErrInstanceInUse = errors.New("a database on this instance is attached to an application; detach it first") ErrInstanceRunning = errors.New("stop the database before deleting it") ErrInstanceOwned = errors.New("database is owned by another resource") // Upgrade errors. ErrInvalidVersion = errors.New("invalid target version") ErrAlreadyOnVersion = errors.New("instance is already on this version") ErrDowngrade = errors.New("downgrade is not supported; data written by a newer version may be unreadable") ErrMongoMajorUpgrade = errors.New("MongoDB major-version upgrades must be applied one major at a time and are not yet automated; create a new instance and migrate, or upgrade within the same major") ErrUpgradeInProgress = errors.New("an upgrade is already in progress for this instance") ErrInstanceNotUpgradable = errors.New("instance must be running or stopped to upgrade") ErrDefaultNetwork = errors.New("the workspace default network cannot be detached") ErrNoNetworkProvider = errors.New("network management is not available") )
ErrNoSharedInstance is returned when placement "shared" finds no compatible running instance to host the dependency's logical database.
Functions ¶
func InstancePasswordSecretName ¶
func InstancePasswordSecretName(inst *models.DatabaseInstance) string
InstancePasswordSecretName / InstanceURLSecretName are the names for an instance-level secret (Redis, which has no logical databases).
func InstanceURLSecretName ¶
func InstanceURLSecretName(inst *models.DatabaseInstance) string
func PasswordSecretName ¶
func PasswordSecretName(inst *models.DatabaseInstance, db *models.Database) string
PasswordSecretName / URLSecretName are the canonical Vault names for a logical database's scoped-user password and full connection URL. The instance slug is unique per workspace, so the names don't collide across instances.
func URLSecretName ¶
func URLSecretName(inst *models.DatabaseInstance, db *models.Database) string
Types ¶
type AppController ¶
type AppController interface {
StopByID(ctx context.Context, workspaceID, appID uint) error
StartByID(ctx context.Context, workspaceID, appID uint) error
}
AppController stops/starts the applications that use a database while it is being upgraded, so writers are quiesced during a major (copy) upgrade. Wired over the application service by the composition root (an interface here keeps the database service free of an app-service dependency).
type AppDatabase ¶
type AppDatabase struct {
models.Database
InstanceName string `json:"instance_name"`
Engine models.DBEngine `json:"engine"`
Host string `json:"host"`
Port int `json:"port"`
}
AppDatabase is a logical database enriched with its instance's engine and network address, for display on an application.
type ConnectionInfo ¶
type ConnectionInfo struct {
Host string `json:"host"`
Port int `json:"port"`
Username string `json:"username"`
Password string `json:"password"`
Database string `json:"database"`
URI string `json:"uri"`
}
ConnectionInfo is the (sensitive) connection detail for a database.
type DumpRef ¶
DumpRef is an opaque handle to a logical-database dump produced by Dump and consumed by Load (the artifact filename + the node volume it lives on).
type EngineDefault ¶
type EngineDefault struct {
Engine models.DBEngine `json:"engine"`
Image string `json:"image"` // effective default image ref
Version string `json:"version"` // default tag
}
EngineDefault is the resolved default image/version for an engine, used to prefill the create form so it reflects the admin's deployment-config tags.
type Enqueuer ¶
type Enqueuer interface {
EnqueueProvisionDB(instanceID, serverID uint) error
EnqueueUpgradeDB(instanceID, serverID uint, target, path string, stopApps bool) error
}
Enqueuer schedules background provisioning. Implemented by the worker producer; an interface here avoids a database->worker import cycle.
type ImageResolver ¶
ImageResolver resolves a deployment-config catalog key to an image ref.
type LiveStatus ¶
type LiveStatus struct {
Status string `json:"status"` // headline: stored lifecycle, or live-derived when running
StoredStatus models.DBStatus `json:"stored_status"`
ContainerState string `json:"container_state,omitempty"`
Health string `json:"health,omitempty"`
Running bool `json:"running"`
Restarting bool `json:"restarting"`
RestartCount int `json:"restart_count"`
ExitCode int `json:"exit_code"`
StartedAt string `json:"started_at,omitempty"`
UptimeSeconds int64 `json:"uptime_seconds"`
HasContainer bool `json:"has_container"`
Upgrade *models.UpgradeProgress `json:"upgrade,omitempty"`
Stats *docker.StatsSample `json:"stats,omitempty"`
}
LiveStatus is a lightweight, pollable view of an instance's state: the stored lifecycle status (provisioning/running/stopped/failed/upgrading) plus, when a container exists, its live Docker state and a stats snapshot. The detail page polls this so a user sees provisioning finish — or a crash — without a manual refresh. Mirrors the application LiveStatus endpoint.
type LogicalBackup ¶
type LogicalBackup interface {
Dump(ctx context.Context, inst *models.DatabaseInstance, db *models.Database) (DumpRef, error)
Load(ctx context.Context, inst *models.DatabaseInstance, db *models.Database, ref DumpRef, force bool) error
}
LogicalBackup dumps and restores a single logical database. Wired over the backup service by the composition root (keeps the database service decoupled from the backup package and its types).
type NetworkProvider ¶
type NetworkProvider interface {
EnsureDefault(ctx context.Context, workspaceID uint) (*models.Network, error)
Get(workspaceID, id uint) (*models.Network, error)
}
NetworkProvider resolves workspace Docker networks so a database joins the same networks its applications do — the default network always, plus any custom networks the user attaches. Implemented by the network service.
type NodeDocker ¶
NodeDocker resolves the Docker client for a node id (0 = local).
type NodeGuard ¶
NodeGuard validates that a node can accept a new placement (exists, not cordoned). Implemented by the node service; injected after construction.
type OwnerExister ¶
OwnerExister reports whether an owning resource of the given kind/id still exists in the workspace, letting Delete refuse to orphan a database that still backs an app/stack. Wired by the composition root to avoid depending on the app/stack repositories directly.
type Placement ¶
type Placement string
Placement decides how a database dependency is satisfied against the workspace. It is shared by the marketplace installer and the declarative (GitOps) apply so both honor the same semantics.
const ( // PlacementAuto reuses a compatible running instance when one exists (creating // a dedicated logical database on it), otherwise provisions a fresh instance. PlacementAuto Placement = "auto" // PlacementDedicated always provisions a fresh instance for the dependency. PlacementDedicated Placement = "dedicated" // a dedicated logical database on it; it never provisions a new instance. PlacementShared Placement = "shared" )
type SecretWriter ¶
type SecretWriter interface {
UpsertOwned(workspaceID uint, ownerKind string, ownerID uint, name, value, description string) (*models.Secret, error)
DeleteOwned(workspaceID uint, ownerKind string, ownerID uint) ([]models.Application, error)
}
SecretWriter manages the Vault secrets owned by a managed database. Implemented by the secret service; injected after construction (optional — nil disables auto-provisioning and the cascade, falling back to plaintext env injection).
type ServerInfo ¶
ServerInfo resolves a node's display metadata by id. Implemented by the node service; injected after construction (optional — read paths degrade to an empty server name when unset, e.g. in the worker).
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
func NewService ¶
func NewService(repo *repositories.DatabaseRepository, clients NodeDocker, enqueuer Enqueuer) *Service
func (*Service) AttachNetwork ¶
func (s *Service) AttachNetwork(ctx context.Context, workspaceID, instanceID, networkID uint) (*models.DatabaseInstance, error)
AttachNetwork connects the instance to an additional workspace network and, when its container exists, attaches it live (no restart). Idempotent.
func (*Service) AttachToApp ¶
func (s *Service) AttachToApp(workspaceID, dbID, appID uint, envPrefix string) (*models.Database, error)
AttachToApp links an existing logical database to an application, recording the env prefix used for its injected connection vars. Returns the updated database. Node-affinity and cross-app checks are the caller's responsibility.
func (*Service) CreateDatabase ¶
func (s *Service) CreateDatabase(ctx context.Context, workspaceID, instanceID uint, name string, appID *uint) (*models.Database, error)
CreateDatabase provisions a new logical database (with its own scoped user) on a running SQL instance by running the engine client as a one-shot container.
func (*Service) DatabaseConnection ¶
func (s *Service) DatabaseConnection(inst *models.DatabaseInstance, d *models.Database) (ConnectionInfo, error)
DatabaseConnection returns the decrypted connection info for a logical database (sensitive — admin only).
func (*Service) DatabaseConnectionForApp ¶
func (s *Service) DatabaseConnectionForApp(workspaceID, appID, dbID uint) (ConnectionInfo, error)
DatabaseConnectionForApp reveals the connection for a logical database that belongs to the given application (the app's own scoped credentials — not the instance admin credentials).
func (*Service) Delete ¶
Delete stops and removes the instance container, its data volume, and its logical database records (their data lives in the dropped container). Refuses while the instance is running, or when any of its databases is still attached to an application.
func (*Service) DeleteDatabase ¶
DeleteDatabase drops a logical database and its user from the instance.
func (*Service) DetachFromApp ¶
DetachFromApp unlinks a logical database from its application, clearing the owner and env prefix. Returns the updated database (with its prior prefix so the caller can clean up injected env vars before it is cleared on the row).
func (*Service) DetachNetwork ¶
func (s *Service) DetachNetwork(ctx context.Context, workspaceID, instanceID, networkID uint) (*models.DatabaseInstance, error)
DetachNetwork disconnects the instance from a network. The workspace default network (which carries the alias apps reach the instance by) cannot be removed.
func (*Service) EngineDefaults ¶
func (s *Service) EngineDefaults() []EngineDefault
EngineDefaults returns the resolved default image+version per engine (from the deployment-config catalog), in a stable order.
func (*Service) FindDatabaseByDeclName ¶
func (s *Service) FindDatabaseByDeclName(workspaceID uint, declName string) (*models.Database, *models.DatabaseInstance, bool)
FindDatabaseByDeclName returns the logical database stamped with the given declarative name and its hosting instance; ok is false when none exists.
func (*Service) FindReusableInstance ¶
func (s *Service) FindReusableInstance(workspaceID uint, engine models.DBEngine) *models.DatabaseInstance
FindReusableInstance returns the running instance a shared/auto placement would reuse for engine, or nil. Exposed so a caller can pre-resolve a dependency's target node without performing the placement.
func (*Service) GetDatabase ¶
GetDatabase loads a logical database scoped to the workspace.
func (*Service) InstanceConnection ¶
func (s *Service) InstanceConnection(inst *models.DatabaseInstance) (ConnectionInfo, error)
InstanceConnection returns the admin/direct connection for an instance. Used for Redis (which has no logical databases) and for diagnostics.
func (*Service) ListByApp ¶
func (s *Service) ListByApp(workspaceID, appID uint) ([]AppDatabase, error)
ListByApp returns the logical databases attached to an application, each with its instance's engine and address.
func (*Service) ListDatabases ¶
ListDatabases returns an instance's logical databases.
func (*Service) ListDatabasesByWorkspace ¶
ListDatabasesByWorkspace returns every logical database in the workspace.
func (*Service) LiveStatus ¶
func (s *Service) LiveStatus(ctx context.Context, inst *models.DatabaseInstance) LiveStatus
LiveStatus inspects the instance's container and returns its real-time status. Falls back to the stored status when there is no container yet (provisioning), it was removed, or the node is unreachable — so polling always gets an answer.
func (*Service) MaybeRefreshSizes ¶
func (s *Service) MaybeRefreshSizes(inst *models.DatabaseInstance)
MaybeRefreshSizes lazily refreshes an instance's sizes in the background when they are stale (older than sizeSyncTTL) and the instance is running. It never blocks the caller and debounces concurrent triggers per instance, so a detail-page load returns immediately with the current (possibly slightly stale) values and the next load shows fresh ones.
func (*Service) PlanUpgrade ¶
func (s *Service) PlanUpgrade(workspaceID, instanceID uint, target string) (*UpgradePlan, error)
PlanUpgrade resolves (without mutating) how an upgrade to target would run, or an error for a same-version/downgrade/invalid target.
func (*Service) PrepareDatabase ¶
func (s *Service) PrepareDatabase(workspaceID, instanceID uint, name string, appID *uint) (*models.Database, error)
PrepareDatabase reserves a logical database (record + scoped credentials) on an instance WITHOUT running DDL, so a caller can wire an application's connection env before the instance has finished provisioning. The actual CREATE DATABASE/USER runs later, when the instance comes up (applyPendingDatabases in RunProvision). For an already-running instance use CreateDatabase, which creates it immediately.
func (*Service) Provision ¶
func (s *Service) Provision(ctx context.Context, workspaceID, serverID uint, name string, engine models.DBEngine, version string, volumeSizeBytes int64, meta, annotations models.Metadata) (*models.DatabaseInstance, error)
Provision creates the instance record (admin credentials and connection details known up front) and enqueues the container bring-up to the worker.
func (*Service) RecreateDatabase ¶
func (s *Service) RecreateDatabase(ctx context.Context, inst *models.DatabaseInstance, db *models.Database) error
RecreateDatabase drops and recreates a logical database (and its user) with the same credentials — a clean slate for a force restore. Satisfies the backup service's DDLRunner.
func (*Service) Reencrypt ¶
Reencrypt re-encrypts the workspace's database secrets (instance admin passwords + libSQL keys, and each logical database's password) under the workspace's active DEK. Idempotent; returns the number rewritten.
func (*Service) ResolveDependency ¶
func (s *Service) ResolveDependency(ctx context.Context, workspaceID, serverID, pinInstance uint, base, declName string, engine models.DBEngine, version string, placement Placement, meta models.Metadata) (*models.DatabaseInstance, *models.Database, ConnectionInfo, bool, error)
ResolveDependency satisfies a database dependency per its placement. It returns the hosting instance, the app-scoped logical database (nil for Redis/libSQL or the admin-connection fallback), a connection for the app to use, and whether a new instance was provisioned.
declName, when non-empty, is stamped on the logical database (with the managed-by / gitops-source provenance from meta) so a declarative reconcile can map the manifest Database name back to this exact logical database — rather than guessing by instance name or "first database on the instance". Marketplace installs pass an empty declName (their app env is materialized at install time, not reconciled).
pinInstance, when non-zero, forces a logical database onto that specific instance (the install wizard's explicit choice), ignoring placement.
Newly provisioned instances come up asynchronously, so their logical database is reserved (PrepareDatabase, deferred DDL); reused running instances get the database created immediately (CreateDatabase). Redis and libSQL host no user-managed logical databases, so the app receives the instance connection.
func (*Service) RunProvision ¶
RunProvision performs the container bring-up for an instance (worker-invoked).
func (*Service) RunUpgradeJob ¶
func (s *Service) RunUpgradeJob(ctx context.Context, instanceID uint, target, path string, stopApps bool) error
RunUpgradeJob executes a queued upgrade end-to-end (worker-invoked). It is panic-safe and always returns nil — failures are recorded on persisted progress rather than retried, since a half-applied upgrade must not be blindly re-run.
func (*Service) SetAppController ¶
func (s *Service) SetAppController(a AppController)
SetAppController wires the app stop/start used to quiesce writers during an upgrade (nil-safe: when unset, apps are never auto-stopped).
func (*Service) SetEventBus ¶
SetEventBus wires the in-process bus used to stream live instance status over SSE. Inject the SAME bus into the HTTP-facing and embedded-worker services so worker-driven phase changes reach an open stream (nil-safe).
func (*Service) SetImageResolver ¶
func (s *Service) SetImageResolver(r ImageResolver)
SetImageResolver wires the deployment-config resolver used to pin engine images at provision time. Optional (request-side; the worker uses the pinned image).
func (*Service) SetLogicalBackup ¶
func (s *Service) SetLogicalBackup(b LogicalBackup)
SetLogicalBackup wires the dump/restore engine used by the copy (major) upgrade path and to take a safety backup (nil-safe).
func (*Service) SetNetworkProvider ¶
func (s *Service) SetNetworkProvider(p NetworkProvider)
SetNetworkProvider wires the resolver for workspace networks, where databases run alongside the workspace's applications. Optional (request-side): when unset, databases fall back to the shared gateway network.
func (*Service) SetNodeGuard ¶
SetNodeGuard wires the placement guard consulted when provisioning on a node.
func (*Service) SetOwner ¶
SetOwner records the owning resource (app/stack/user) on an existing instance's metadata. Used to back-link a template's database to the app/stack it backs once those have been created. Built-in keys are authoritative, so this overrides any prior owner.
func (*Service) SetOwnerExister ¶
func (s *Service) SetOwnerExister(fn OwnerExister)
SetOwnerExister wires the owner-existence check used by Delete (nil-safe).
func (*Service) SetSecrets ¶
func (s *Service) SetSecrets(w SecretWriter)
SetSecrets wires the Vault writer that auto-provisions a database's connection secrets and cascades their deletion. Optional (request-side only).
func (*Service) SetServerInfo ¶
func (s *Service) SetServerInfo(si ServerInfo)
SetServerInfo wires the resolver used to annotate instances with their node's display name on read paths.
func (*Service) Stop ¶
Stop stops the instance container and marks it stopped. The data volume and records are retained, so the instance can be started again later.
func (*Service) StreamLogs ¶
func (s *Service) StreamLogs(ctx context.Context, workspaceID, instanceID uint, follow bool, tail string, sink func(docker.LogLine) error) error
StreamLogs follows the instance container's logs, invoking sink for each line. tail bounds the initial backlog ("" = a sensible default / all). When follow is true it then follows live output until the context is cancelled; when false it returns after the tail.
func (*Service) StreamStatus ¶
func (s *Service) StreamStatus(ctx context.Context, inst *models.DatabaseInstance, send func(eventbus.Event) error) error
StreamStatus sends the instance's current status, then live updates, until the context is cancelled (client disconnect). It backs the detail page's SSE. When no bus is wired it sends the initial snapshot and holds the connection open (the client still has its REST fallback).
func (*Service) StreamWorkspaceStatus ¶
func (s *Service) StreamWorkspaceStatus(ctx context.Context, workspaceID uint, send func(eventbus.Event) error) error
StreamWorkspaceStatus streams lifecycle status changes for every instance in a workspace until the context is cancelled (client disconnect). It backs the Databases list's live updates, delivering {id,status} deltas. The list seeds its initial state via the REST list, so no snapshot is sent here. When no bus is wired the connection is held open and the client falls back to its periodic reconcile.
func (*Service) SyncSizes ¶
SyncSizes refreshes the on-disk size of an instance and its logical databases by querying the engine. Requires the instance to be running.
func (*Service) UniqueDatabaseName ¶
UniqueDatabaseName derives a sanitized logical-database name from base that is free on the instance, appending _2, _3, … only on collision. This lets callers (e.g. marketplace installs) use a meaningful, readable name — the install's name — without ever hitting ErrNameTaken.
func (*Service) Upgrade ¶
func (s *Service) Upgrade(ctx context.Context, workspaceID, instanceID uint, target string, stopApps bool) (*models.DatabaseInstance, error)
Upgrade validates a version upgrade, marks the instance "upgrading", and enqueues the work onto the asynq worker (durable across restarts). Callers poll Get for the persisted progress.
stopApps quiesces the apps using the database before the upgrade and restarts them after — strongly recommended for a major (copy) upgrade to avoid losing writes made during the dump.
func (*Service) UpgradeOptions ¶
func (s *Service) UpgradeOptions(workspaceID, instanceID uint) (*UpgradeOptions, error)
UpgradeOptions returns the suggested targets and affected apps for an instance.
type StatusEvent ¶
type StatusEvent struct {
Status models.DBStatus `json:"status"`
Upgrade *models.UpgradeProgress `json:"upgrade,omitempty"`
}
StatusEvent is the snapshot pushed on the "status" stream: the instance's lifecycle status and any in-flight upgrade progress. The detail page replaces its state from this, so a status/phase change needs no extra request.
type UpgradeOptions ¶
type UpgradeOptions struct {
CurrentVersion string `json:"current_version"`
Engine models.DBEngine `json:"engine"`
Suggestions []string `json:"suggestions"` // curated newer versions (hints; any version is accepted)
AffectedAppIDs []uint `json:"affected_app_ids"` // apps that would be stopped for a copy upgrade
}
UpgradeOptions describes what an instance can be upgraded to.
type UpgradePlan ¶
type UpgradePlan struct {
FromVersion string `json:"from_version"`
ToVersion string `json:"to_version"`
Path string `json:"path"` // in-place | dump-restore
Major bool `json:"major"` // crosses a major version
AffectedAppIDs []uint `json:"affected_app_ids"`
}
UpgradePlan is the resolved effect of upgrading to a specific target version.
type WorkspaceStatusEvent ¶
type WorkspaceStatusEvent struct {
ID uint `json:"id"`
Status models.DBStatus `json:"status"`
Upgrade *models.UpgradeProgress `json:"upgrade,omitempty"`
}
WorkspaceStatusEvent is StatusEvent plus the instance id, so a workspace-wide subscriber (the list page) knows which row changed.