Documentation
¶
Overview ¶
Package state 是 fleetly 控制面状态层(SQLite 权威态 + 底座观测缓存 + 写前直读端口)。
分层判据与权威归属(state-model §2.1,本包实现的真源):
- 权威态:只存无法从底座重算的知识——期望态(apps/revisions/env_vars/ domains/placements)、历史(deployments/events/audit_log)、凭证 (tokens)、备份台账(state_backups)、孤儿登记(orphans)。
- 派生缓存:nodes 表 = Docker/Swarm 观测快照,每行带 observed_at/stale, 可整表重建,禁止用于决策(state-model §2.2)。平台不承诺任何底座侧 存活时间戳(Swarm 不暴露该概念),平台观测时间字段为 last_seen_at。
- 实时直读:写操作先直读底座并以对象版本作乐观令牌,冲突返回 E_STATE_VERSION_CONFLICT(resolve.go 的 VersionResolver)。
审计 fail-closed(state-model §2.9):破坏性/管理操作与业务写同事务, 审计写失败即操作失败(audit.go,事务内 WriteAudit)。事件 seq 单调 (events.go,AUTOINCREMENT 永不复用),SSE 游标早于保留窗返回 E_EVENT_CURSOR_EXPIRED(410)并附 oldest_seq。删除走 tombstone-first (apps.go:deleting → deleted 状态位,恢复不复活)。
节点身份(state-model §2.3):领域身份 = 平台节点 ID(n_<ULID>),写入 Swarm node label fleetly.node-id;Swarm node ID 仅存适配器映射 runtime_node_refs(platform_id, swarm_node_id)。
底座访问经 DockerClient 小端口(docker.go)抽象,moby/client 实现见 internal/substrate 适配器——为架构 §2.8 端口纪律打底,核心不出现 第三方类型。
本包不依赖任何框架类型(D20:框架只做装配与生命周期);lynx.Service / lynx.Checker 的装配壳在 cmd/fleetlyd(CheckHealth 方法为结构性实现)。
Index ¶
- Constants
- Variables
- func CanTransitionDeployment(from, to DeploymentStatus) bool
- func DeploymentsRoot(dbPath string) string
- func DiffSummary(kvs ...any) string
- func HashToken(plaintext string) string
- func IsReservedLabel(key string) bool
- func PersistDeploymentCompose(root, deploymentID string, compose []byte) (string, error)
- func RelevantForObservation(ev SubstrateEvent) bool
- func SchemaVersions(ctx context.Context, path string) (dbVersion, maxVersion int64, err error)
- func ValidateEnvKey(key string) error
- type App
- type AppGitConfig
- type AppLifecycle
- type AppSourceWrite
- type AuditEntry
- type AuditRecord
- type BackupWrite
- type BuildRecord
- type BuildStatus
- type CachedNode
- type DeployRecord
- type DeploymentPatch
- type DeploymentStatus
- type DockerClient
- type Domain
- type DomainServiceRoutes
- type Driver
- type EnvVar
- type EnvVarStatus
- type Event
- type EventRecord
- type GitKey
- type GitKeyWrite
- type Janitor
- func (j *Janitor) AuditRetention() time.Duration
- func (j *Janitor) EventRetention() time.Duration
- func (j *Janitor) PruneOnce(ctx context.Context, now time.Time) (events int64, audits int64, err error)
- func (j *Janitor) Start(ctx context.Context) error
- func (j *Janitor) Stop(_ context.Context) error
- type JanitorConfig
- type NodeIdentity
- func (n *NodeIdentity) Anchor(ctx context.Context) error
- func (n *NodeIdentity) Anchored() bool
- func (n *NodeIdentity) CheckHealth() error
- func (n *NodeIdentity) EnsurePlatformID(ctx context.Context) (string, error)
- func (n *NodeIdentity) PlatformID() string
- func (n *NodeIdentity) Start(ctx context.Context) error
- func (n *NodeIdentity) Stop(_ context.Context) error
- type ObjectKind
- type ObjectVersion
- type Observer
- type Placement
- type PlacementSource
- type PlacementState
- type PlacementWrite
- type Revision
- type RevisionWrite
- type RuntimeNodeRef
- type SourceAuthKind
- type StateBackup
- type Store
- func (s *Store) AppHasNonTerminalDeployment(ctx context.Context, appID string) (bool, error)
- func (s *Store) AuthenticateToken(ctx context.Context, plaintext string) (Token, error)
- func (s *Store) BindPlacement(ctx context.Context, w PlacementWrite) (Placement, error)
- func (s *Store) CheckHealth() error
- func (s *Store) ClaimBuild(ctx context.Context, id string) error
- func (s *Store) Close() error
- func (s *Store) CountGitDeploymentsForSHA(ctx context.Context, appID, sha string) (int64, error)
- func (s *Store) CreateApp(ctx context.Context, appID, name string) (App, error)
- func (s *Store) CreateBuild(ctx context.Context, rec BuildRecord) (BuildRecord, error)
- func (s *Store) CreateBuildAs(ctx context.Context, rec BuildRecord, audit *AuditEntry) (BuildRecord, error)
- func (s *Store) CreateDeployment(ctx context.Context, rec DeployRecord) (DeployRecord, error)
- func (s *Store) CreateGitKey(ctx context.Context, w GitKeyWrite) (GitKey, error)
- func (s *Store) CreateToken(ctx context.Context, w TokenWrite) (Token, error)
- func (s *Store) DeleteAppDomains(ctx context.Context, appID string) error
- func (s *Store) DeleteAppEnv(ctx context.Context, appID, key string) error
- func (s *Store) DeleteStateBackup(ctx context.Context, id string) (string, error)
- func (s *Store) EnterPhase(ctx context.Context, id string, from, to DeploymentStatus, ...) error
- func (s *Store) EventsSince(ctx context.Context, since int64, limit int) ([]Event, error)
- func (s *Store) FailStrandedBuild(ctx context.Context, id, errorCode, reason string) error
- func (s *Store) FindBuildsByDigest(ctx context.Context, digest string) ([]BuildRecord, error)
- func (s *Store) FinishBuildFailed(ctx context.Context, id, errorCode string) error
- func (s *Store) FinishBuildSucceeded(ctx context.Context, id, imageRef, imageDigest, planPath, logPath string) error
- func (s *Store) GetAppByID(ctx context.Context, id string) (App, error)
- func (s *Store) GetAppByName(ctx context.Context, name string) (App, error)
- func (s *Store) GetAppDerivedState(ctx context.Context, appID string) (string, error)
- func (s *Store) GetAppDriftConverge(ctx context.Context, appID string) (bool, error)
- func (s *Store) GetAppEnv(ctx context.Context, appID, key string) (EnvVar, error)
- func (s *Store) GetAppGitConfig(ctx context.Context, appID string) (AppGitConfig, error)
- func (s *Store) GetAppRevision(ctx context.Context, appID, revisionID string) (Revision, error)
- func (s *Store) GetAppVolume(ctx context.Context, appID, key string) (Volume, error)
- func (s *Store) GetBuild(ctx context.Context, id string) (BuildRecord, error)
- func (s *Store) GetDeployment(ctx context.Context, id string) (DeployRecord, error)
- func (s *Store) GetGitKeyByFingerprint(ctx context.Context, fingerprint string) (GitKey, error)
- func (s *Store) GetMeta(ctx context.Context, key string) (string, error)
- func (s *Store) GetPlacement(ctx context.Context, appID string) (Placement, error)
- func (s *Store) GetRevision(ctx context.Context, id string) (Revision, error)
- func (s *Store) GetRuntimeNodeRef(ctx context.Context, platformID string) (RuntimeNodeRef, error)
- func (s *Store) HasAnyToken(ctx context.Context) (bool, error)
- func (s *Store) InTx(ctx context.Context, fn func(tx *Tx) error) (err error)
- func (s *Store) LatestDeploymentsByApp(ctx context.Context, appIDs []string, perApp int) (map[string][]DeployRecord, error)
- func (s *Store) LatestStateBackup(ctx context.Context) (*StateBackup, error)
- func (s *Store) ListActiveApps(ctx context.Context) ([]App, error)
- func (s *Store) ListAllDomains(ctx context.Context) ([]Domain, error)
- func (s *Store) ListAppBuilds(ctx context.Context, appID string, limit int) ([]BuildRecord, error)
- func (s *Store) ListAppDeployments(ctx context.Context, appID string, limit int) ([]DeployRecord, error)
- func (s *Store) ListAppDomains(ctx context.Context, appID string) ([]Domain, error)
- func (s *Store) ListAppEnv(ctx context.Context, appID string) ([]EnvVar, error)
- func (s *Store) ListAppVolumes(ctx context.Context, appID string) ([]Volume, error)
- func (s *Store) ListAppsByLifecycle(ctx context.Context, lifecycle AppLifecycle) ([]App, error)
- func (s *Store) ListCachedNodes(ctx context.Context) ([]CachedNode, error)
- func (s *Store) ListGitKeys(ctx context.Context) ([]GitKey, error)
- func (s *Store) ListNonTerminalBuilds(ctx context.Context) ([]BuildRecord, error)
- func (s *Store) ListNonTerminalDeployments(ctx context.Context) ([]DeployRecord, error)
- func (s *Store) ListRevisions(ctx context.Context, appID string) ([]Revision, error)
- func (s *Store) ListStateBackups(ctx context.Context, n int) ([]StateBackup, error)
- func (s *Store) ListTokens(ctx context.Context) ([]Token, error)
- func (s *Store) MarkAllNodesStale(ctx context.Context) error
- func (s *Store) MarkAppDeleted(ctx context.Context, appID string) error
- func (s *Store) MarkAppDeleting(ctx context.Context, appID string) error
- func (s *Store) MarkAppEnvEffective(ctx context.Context, appID string) (int, error)
- func (s *Store) MarkAppVolumesOrphaned(ctx context.Context, appID string) (int, error)
- func (s *Store) NextQueuedBuilds(ctx context.Context, limit int) ([]BuildRecord, error)
- func (s *Store) NextQueuedDeployments(ctx context.Context, limit int) ([]DeployRecord, error)
- func (s *Store) OldestSeq(ctx context.Context) (int64, bool, error)
- func (s *Store) Path() string
- func (s *Store) Ping(ctx context.Context) error
- func (s *Store) PlacementByApp(ctx context.Context, appIDs []string) (map[string]Placement, error)
- func (s *Store) PruneExpiredAudits(ctx context.Context, cutoff time.Time) (int64, error)
- func (s *Store) PruneExpiredEvents(ctx context.Context, cutoff time.Time) (int64, error)
- func (s *Store) PruneTerminalBuildsOlderThan(ctx context.Context, cutoff time.Time) (int64, error)
- func (s *Store) RecentAudits(ctx context.Context, n int) ([]AuditRecord, error)
- func (s *Store) RecordStateBackup(ctx context.Context, w BackupWrite) (StateBackup, error)
- func (s *Store) RegisterAppVolume(ctx context.Context, w VolumeWrite) (Volume, bool, error)
- func (s *Store) RemoveGitKey(ctx context.Context, id, actorTokenID string) error
- func (s *Store) ReplaceAppDomains(ctx context.Context, appID string, declared []DomainServiceRoutes) error
- func (s *Store) ResetInterruptedBuilds(ctx context.Context, errorCode, reason string) (int, error)
- func (s *Store) RevokeToken(ctx context.Context, id, actorTokenID string) error
- func (s *Store) RevokeTokenGuardLastAdmin(ctx context.Context, id, actorTokenID string, isAdmin func(scopes string) bool) error
- func (s *Store) SchemaVersion(ctx context.Context) (int64, error)
- func (s *Store) SetAppEnv(ctx context.Context, appID, key, value, source string) (EnvVar, error)
- func (s *Store) SetAppSource(ctx context.Context, appID string, w AppSourceWrite) error
- func (s *Store) SetAppWebhookSecret(ctx context.Context, appID, ciphertext, actorTokenID string) error
- func (s *Store) SetBuildLogPath(ctx context.Context, id, logPath string) error
- func (s *Store) SetDomainCert(ctx context.Context, appID, domain, certSHA256 string, notAfter time.Time) error
- func (s *Store) SetMeta(ctx context.Context, key, value string) error
- func (s *Store) SyncNodeObservations(ctx context.Context, nodes []SubstrateNode, at time.Time) error
- func (s *Store) TerminalDeploymentIDsOlderThan(ctx context.Context, cutoff time.Time) (map[string]bool, error)
- func (s *Store) TouchTokenUsed(ctx context.Context, id string) error
- func (s *Store) UpdateDeployment(ctx context.Context, id string, p DeploymentPatch) error
- func (s *Store) UpsertRuntimeNodeRef(ctx context.Context, platformID, swarmNodeID string, anchoredAt time.Time) (bool, error)
- func (s *Store) VacuumInto(ctx context.Context, target string) error
- type SubstrateEvent
- type SubstrateNode
- type Token
- type TokenWrite
- type Tx
- func (t *Tx) AppendEvent(ctx context.Context, e Event) (int64, error)
- func (t *Tx) BindPlacement(ctx context.Context, w PlacementWrite) (Placement, error)
- func (t *Tx) CountGitDeploymentsForSHA(ctx context.Context, appID, sha string) (int64, error)
- func (t *Tx) CreateApp(ctx context.Context, appID, name string) (App, error)
- func (t *Tx) CreateBuild(ctx context.Context, rec BuildRecord) (BuildRecord, error)
- func (t *Tx) CreateDeployment(ctx context.Context, rec DeployRecord) (DeployRecord, error)
- func (t *Tx) CreateRevision(ctx context.Context, w RevisionWrite) (Revision, error)
- func (t *Tx) EnterPhase(ctx context.Context, id string, from, to DeploymentStatus, ...) error
- func (t *Tx) GetAppDerivedState(ctx context.Context, appID string) (string, error)
- func (t *Tx) GetAppDriftConverge(ctx context.Context, appID string) (bool, error)
- func (t *Tx) GetAppEnv(ctx context.Context, appID, key string) (EnvVar, error)
- func (t *Tx) GetAppVolume(ctx context.Context, appID, key string) (Volume, error)
- func (t *Tx) GetPlacement(ctx context.Context, appID string) (Placement, error)
- func (t *Tx) MarkAppDeleted(ctx context.Context, appID string) error
- func (t *Tx) MarkAppDeleting(ctx context.Context, appID string) error
- func (t *Tx) RegisterAppVolume(ctx context.Context, w VolumeWrite) (Volume, error)
- func (t *Tx) ReplaceAppDomains(ctx context.Context, appID string, declared []DomainServiceRoutes) error
- func (t *Tx) ReusableRevisionByDesiredHash(ctx context.Context, appID, desiredHash string) (Revision, bool, error)
- func (t *Tx) SetAppDerivedState(ctx context.Context, appID, expected, next string) error
- func (t *Tx) SetAppDriftConverge(ctx context.Context, appID string, on bool) error
- func (t *Tx) SetAppEnv(ctx context.Context, appID, key, value, source string) (EnvVar, error)
- func (t *Tx) SetMeta(ctx context.Context, key, value string) error
- func (t *Tx) UpdateDeployment(ctx context.Context, id string, p DeploymentPatch) error
- func (t *Tx) WriteAudit(ctx context.Context, e AuditEntry) error
- type VersionResolver
- type Volume
- type VolumeKind
- type VolumeStatus
- type VolumeWrite
Constants ¶
const ( // AppStateRunning 以上皆否。 AppStateRunning = "running" // AppStateDegraded 运行中但有不合格判定(观察窗失败 verdict=unstable / // 窗后不稳定 / W_DEPLOY_INSTABILITY)。 AppStateDegraded = "degraded" // AppStateBlocked 平台侧无合法动作可执行(placement blocked/unresolved)。 AppStateBlocked = "blocked" // AppStateDown 无有效版本或首发失败 scale=0(没有任何期望实例)。 AppStateDown = "down" )
AppDerivedState 词表(state-model §2.10)。
const ( BackupKindDaily = "daily" BackupKindPreUpgrade = "pre_upgrade" BackupKindPostDeploy = "post_deploy" BackupKindManual = "manual" )
备份 kind 词表(00008 CHECK 的包内镜像;写入入口校验用)。
const ( BackupVerifyPending = "pending" BackupVerifyVerified = "verified" BackupVerifyFailed = "failed" )
verify_status 词表。
const ( // RecoveryReplay 已按最后有效 revision 归位重放(未切流失败/cancel; // 值取 replay——restore 专指 DR 灾难恢复,见词汇表 restore 词条)。 RecoveryReplay = "replay" // RecoveryBlocked 恢复被阻塞(引擎不可达等;退避重试可续跑)。 RecoveryBlocked = "blocked" )
deployment recovery 词表(recovery 列;同记录恢复记录,D-REL-7)。
const ( // DeployFlagPostWindowAlerted:观察窗后不稳定已告警(L4 一次)。 DeployFlagPostWindowAlerted int64 = 1 << 0 // DeployFlagInstabilityWarning:观察窗警告通过(W_DEPLOY_INSTABILITY)。 DeployFlagInstabilityWarning int64 = 1 << 1 )
部署级标志位(deployments.flags,只增位不回收)。
const ( EventTypeNode = "node" EventTypeService = "service" EventTypeTask = "task" )
观测信号相关的事件类别(Docker events 的 Type 取值子集;变更 1s 内 触发 resync,state-model §2.2)。
const ( DefaultEventRetentionDays = 30 DefaultAuditRetentionDays = 365 )
DefaultEventRetentionDays / DefaultAuditRetentionDays 是保留期默认值 (架构 §2.3:事件 30 天、审计 1 年;config 可调)。
const ( // DefaultBuildRetentionDays 是 builds 终态行保留天数(台账窗口)。 DefaultBuildRetentionDays = 90 // DefaultArtifactsRetentionDays 是 build artifacts 目录保留天数。 DefaultArtifactsRetentionDays = 30 // DefaultDeploymentDirRetentionDays 是部署 compose 持久化目录在部署 // 终态后的保留天数(终态前行恒不清理)。 DefaultDeploymentDirRetentionDays = 30 )
S18-A7/A10 新增保留窗默认值。
const ( // LabelNamespace 是平台 label 保留命名空间前缀。 LabelNamespace = "fleetly." // LabelManaged 标记平台受管对象(服务 label,"true"):归属判定、 // 孤儿检测、删除保护的依据。 LabelManaged = "fleetly.managed" // LabelApp 标记归属应用(服务/容器 label,值为应用名)。 LabelApp = "fleetly.app" // LabelProcess 标记 compose 服务名(应用内进程名)。 LabelProcess = "fleetly.process" // LabelDeployment 标记发布归属(值 = deployment ID)。 LabelDeployment = "fleetly.deployment" // LabelDesiredHash 是服务级期望态哈希(对账变更判据的落点 label, // state-model §2.5 desired-hash 纪律;service-label 变更不触发任务 // 重建——归位零成本的配套,Spike B2)。 LabelDesiredHash = "fleetly.desired-hash" // LabelCron 标记定时任务 schedule(v0.2 契约,常量先行,state-model §2.4)。 LabelCron = "fleetly.cron" // LabelNodeID 是节点身份锚(node label,值 = 平台节点 ID n_<ULID>, // state-model §2.3)。 LabelNodeID = "fleetly.node-id" // LabelDomains 是平台约定路由域名列表(compose 服务 label,逗号分隔)。 LabelDomains = "fleetly.domains" // LabelPlacementNode 是放置意图(compose 服务 label,v0.2 多节点消费, // 常量先行)。 LabelPlacementNode = "fleetly.placement.node" )
fleetly.* label 最小契约(state-model §2.4):保留命名空间 fleetly.* 为平台独占(用户占用 → E_LABEL_RESERVED 422,映射随 API 面落地);写者 唯一 = 适配器 Marker 端口(本阶段仅节点身份锚经 DockerClient.UpdateNodeLabel 写入,业务对象 label 下发随 T2.14);密钥/payload 永不入 label;平台保留 未知 fleetly.* 键不改写。
const ( // RevisionStatusActive 在保留窗内(回滚选项集)。 RevisionStatusActive = "active" // RevisionStatusSuperseded 被更新快照挤出保留窗(存档不删)。 RevisionStatusSuperseded = "superseded" )
保留窗状态位词表(revisions.status,00005 加法列;无 CHECK,词表在此 冻结)。v0.1 只有两个值;候选态(candidate)不进 v0.1——快照仅在成功 终态固化(verified=1 与 active 同拍写入)。
const DefaultGitBranch = "main"
DefaultGitBranch 是 app 配置分支的缺省值(push 与 webhook 共用)。
const JanitorCleanupInterval = time.Hour
JanitorCleanupInterval 是清理扫描周期。
const ManagedLabelValue = "true"
ManagedLabelValue 是 LabelManaged 的约定取值。
const ( // MetaKeyPlatformNodeID 是本机平台节点 ID 的 meta 键(值 = n_<ULID>, // state-model §2.3:首次启动生成、此后持久复用)。 MetaKeyPlatformNodeID = "platform_node_id" )
meta 表:平台自身身份与小规模 settings(state-model §2.1「平台身份与 凭证」行的 settings 载体;v0.1 冻结清单未单列业务表,键值结构随阶段 只增键不改表)。
const NodeIDPrefix = "n_"
NodeIDPrefix 是平台节点 ID 前缀。
const ( // ObservationInterval 是全量 resync 周期(state-model §2.2:统一 30s)。 ObservationInterval = 30 * time.Second )
const ( // PhaseBlockedWaiting 发布中绑定节点 DOWN:看门狗暂停计时、可 cancel // (release-semantics §2.3,场景 15)。 PhaseBlockedWaiting = "blocked_waiting" )
deployment 子状态(phase 列词表;空 = 无子状态)。
const RevisionKeepVersions = 5
RevisionKeepVersions 是保留窗宽度(release-semantics §2.4 / architecture §2.5 默认参数表:版本保留 5)。
const (
// VerdictUnstable 已切流观察窗失败(app=degraded 的来源之一)。
VerdictUnstable = "unstable"
)
deployment verdict 词表(verdict 列;unstable 仅为 deployment 判定)。
Variables ¶
var ( // ErrAppExists 表示同名应用已在册(任何生命周期态名字均占用)。 ErrAppExists = errors.New("app name already registered") // ErrAppTombstoned 表示目标应用处于删除状态位(deleting/deleted): // 不可复活、不可在其上继续业务写。 ErrAppTombstoned = errors.New("app is tombstoned") // ErrAppNotFound 表示应用不存在。 ErrAppNotFound = errors.New("app not found") // ErrInvalidLifecycleTransition 表示生命周期状态位迁移非法 // (状态机:active → deleting → deleted,不可跳越、不可回退)。 ErrInvalidLifecycleTransition = errors.New("invalid app lifecycle transition") )
应用生命周期哨兵错误。
var ( // ErrBuildNotFound 表示构建记录不存在。 ErrBuildNotFound = errors.New("build not found") // ErrBuildStateTransition 表示构建状态迁移非法(终态不可逆、claim // 竞争失败等——调用方应重读状态后裁决)。 ErrBuildStateTransition = errors.New("invalid build state transition") )
构建记录哨兵错误。
var ( // ErrDeploymentNotFound 表示部署记录不存在。 ErrDeploymentNotFound = errors.New("deployment not found") // ErrDeploymentStateTransition 表示部署状态迁移非法(终态不可逆、 // 竞争落败等——调用方重读状态后裁决)。 ErrDeploymentStateTransition = errors.New("invalid deployment state transition") // ErrDuplicateGitDeployment 表示同一 (app, sha) 已有 enqueued/active/ // succeeded 部署、本次入队被判重拒绝(M3-4:webhook sha 幂等去重的 // 事务内复查哨兵——check-then-insert 竞态在入队事务原语内闭合, // 并发重投只建一行)。消费方把它映射为 duplicate 回执(200),非错误 // 面披露。 ErrDuplicateGitDeployment = errors.New("duplicate git deployment for sha") )
DeploymentNotFound 哨兵与状态迁移哨兵。
var ( // ErrObjectNotFound 表示直读的底座对象不存在(可能已被并发删除)。 ErrObjectNotFound = errors.New("substrate object not found") // ErrVersionConflict 表示乐观令牌与底座当前版本不符(并发修改)。 ErrVersionConflict = errors.New("substrate object version conflict") // ErrNotSwarmManager 表示引擎未启用 Swarm(或本机非 manager), // 节点身份锚定与节点观测不可用。 ErrNotSwarmManager = errors.New("docker engine is not an active swarm manager") )
底座端口哨兵错误:适配器将第三方错误归类为以下哨兵(errors.Is 判定), 核心据此映射契约错误码,适配器自身不出现契约码。
var ( // ErrGitKeyNotFound 表示目标 git key 不存在。 ErrGitKeyNotFound = errors.New("git key not found") // ErrGitKeyExists 表示同指纹公钥已在册。 ErrGitKeyExists = errors.New("git key already registered") )
git key 哨兵错误。
var ( // ErrTokenNotFound 表示目标 token 不存在。 ErrTokenNotFound = errors.New("token not found") // ErrTokenRevoked 表示 token 已吊销(认证拒绝路径)。 ErrTokenRevoked = errors.New("token revoked") // ErrTokenInvalid 表示凭据不匹配(哈希查无此行或常量时间比对失败)。 ErrTokenInvalid = errors.New("token invalid") // ErrTokenLastAdmin 表示最后管理员守卫拒绝(M4-6):本次吊销会使 // 平台不存在任何未吊销 admin token——依次吊销全部 admin 后平台锁死 // (重启不补种 bootstrap:HasAnyToken 已见 token 行,一次性语义), // 在吊销事务内拒绝。调用方映射为 409 业务冲突信封。 ErrTokenLastAdmin = errors.New("last admin token") )
token 相关哨兵错误。
var ErrAppDerivedStateConflict = errors.New("app derived state conflict")
ErrAppDerivedStateConflict 表示派生状态 CAS 落败(并发翻转已发生)。
var ErrDomainNotFound = errors.New("domain not found")
ErrDomainNotFound 表示域名台账行不存在。
var ErrEnvNotFound = errors.New("env var not found")
ErrEnvNotFound 表示目标 env 键不存在。
var ErrIllegalTransition = fmt.Errorf("%w: illegal per transition table", ErrDeploymentStateTransition)
ErrIllegalTransition 表示按转移表判定的非法状态迁移(from→to 无边—— 确定性编码错误)。它是 ErrDeploymentStateTransition 的特化(包装链): 既有调用方按「迁移非法家族」处理(errors.Is 双哨兵均真——引擎对竞争 落败的幂等收敛语义不变);需要区分「表外组合」与「CAS 竞争落败」的 调用方(测试、诊断)精确匹配本哨兵——前者应修调用方,后者应重读状态 后裁决。
var ErrPlacementNotFound = errors.New("placement not found")
ErrPlacementNotFound 表示目标应用无绑定记录(有卷应用不存在「无绑定」 的合法运行态——出现即调用方该走自动选点,本哨兵不外溢为 API 错误)。
var ErrRefNotFound = fmt.Errorf("runtime node ref not found")
GetRuntimeNodeRef 按 platform_id 取映射;不存在返回 ("", ErrAppNotFound) 语义即未锚定——用独立哨兵 ErrRefNotFound 表达。
var ErrRevisionNotFound = errors.New("revision not found")
ErrRevisionNotFound 表示版本快照不存在(含 superseded 后不可经选项面 解析的形态——调用方按 E_ROLLBACK_NO_TARGET 映射)。
var ErrVolumeNotFound = errors.New("volume not found")
ErrVolumeNotFound 表示注册表中无该卷。
Functions ¶
func CanTransitionDeployment ¶
func CanTransitionDeployment(from, to DeploymentStatus) bool
CanTransitionDeployment 报告 from → to 是否合法转移(未知状态、终态出边、 表外组合一律非法)。
func DeploymentsRoot ¶
DeploymentsRoot 返回部署 compose 持久化根目录(S18-A7:<数据根>/ deployments;数据根 = 状态库同目录——与 cmd 装配的 BackupRoot/GitRoot 同款派生,入队点(api/gitserver)与 janitor 清理共用同一布局)。
func DiffSummary ¶
DiffSummary 构造审计 diff 摘要 JSON 字符串(B4:审计摘要的唯一构造器 ——内部 json.Marshal,键值含 `"`、`\`、控制字符时按 JSON 规则转义, 消灭手拼 JSON 的注入与破包面)。kvs 为 key,value 成对变参(key 取 string;value 支持 string/数值/布尔等可 marshal 类型);奇数个尾参 丢弃末项(防御式——调用方均为固定键值对)。marshal 失败(理论不可达) 回落 "{}"。map 序列化键序确定(字典序)。
func IsReservedLabel ¶
IsReservedLabel 报告 key 是否落在平台保留命名空间(fleetly.*): 用户声明该命名空间内的 label 时上游应拒绝(E_LABEL_RESERVED)。
func PersistDeploymentCompose ¶
PersistDeploymentCompose 把部署 compose 字节持久化到 <root>/<deploymentID>/compose.yaml(S18-A7 入队点共享写入通道:先写 文件后建行——部署行不指向缺失文件;0600 权限;OS 临时目录自此仅作解析 中转,tmpfiles 清理不再影响引擎 preparing 重载与成功固化重载)。
func RelevantForObservation ¶
func RelevantForObservation(ev SubstrateEvent) bool
RelevantForObservation 报告事件是否应触发观测缓存失效。
func SchemaVersions ¶
SchemaVersions 只读返回(DB 当前 schema 版本,本二进制内嵌迁移的最大 版本)。不开 Store、不应用迁移、不触发 ensureMigrated 的高版本守卫—— 升级/回退编排(fleetlyd schema-version 子命令,F5/S20)需要在旧二进制 「拒绝打开新 schema 库」之前比对两侧版本,给操作员可行动指引或自动 恢复,而不是 start 失败后留下 DEGRADED 现场让人猜。
版本读取口径 = goose 版本表的 MAX(version_id)(本平台迁移只加法、不写 down 行,MAX 即已应用最高版本)。库文件不存在 / 版本表不存在(从未被 fleetlyd 打开过)→ dbVersion 0(空库语义,goose 首启建表落 0)。
func ValidateEnvKey ¶
ValidateEnvKey 校验平台 env 键:非空、无空白、无 = / NUL(注入安全下限, 字符集从宽——compose/Docker 允许点与连字符;窄白名单属过度设计)。
Types ¶
type App ¶
type App struct {
ID string
Name string
Lifecycle AppLifecycle
CreatedAt time.Time
UpdatedAt time.Time
DeletingAt time.Time // 零值 = 未进入删除
DeletedAt time.Time // 零值 = 未完成删除
}
App 是应用权威态行(v0.1 最小面:期望态根 + tombstone 状态位)。
type AppGitConfig ¶
type AppGitConfig struct {
Branch string
// SecretSet 报告 webhook 签名密钥已配置。
SecretSet bool
// WebhookSecret 是密文形态(SecretSet=false 时为空)。
WebhookSecret string
SourceURL string
AuthKind SourceAuthKind
// AuthSecret 是密文形态(” = 无认证材料)。
AuthSecret string
}
AppGitConfig 是 app git 触发配置投影(webhook_secret 携带密文形态, daemon 侧解密消费;api 读面只用 SecretSet)。
type AppLifecycle ¶
type AppLifecycle string
AppLifecycle 是应用生命周期状态位。
const ( // LifecycleActive 正常在册。 LifecycleActive AppLifecycle = "active" // LifecycleDeleting 删除进行中(deleting,等待清理与保留期)。 LifecycleDeleting AppLifecycle = "deleting" // LifecycleDeleted 已删除(tombstone,保留期内名字仍占用)。 LifecycleDeleted AppLifecycle = "deleted" )
type AppSourceWrite ¶
type AppSourceWrite struct {
// URL 为空 = 清除拉源配置(auth 字段一并清空)。
URL string
Branch string
AuthKind SourceAuthKind
AuthSecret string // envelope 密文
// ActorTokenID 审计调用方 token。
ActorTokenID string
}
AppSourceWrite 是一次拉源配置写入(ciphertext 密文形态入参)。
type AuditEntry ¶
type AuditEntry struct {
// ID 记录 ID(ULID;留空自动生成)。
ID string
// At 发生时间(零值取写入时刻)。
At time.Time
// Actor 操作主体:human / ai_agent / system(架构 §1.1 术语约定)。
Actor string
// ActorTokenID 关联 token(可空)。
ActorTokenID string
// Action 稳定动作串(如 app.delete、node.identity_created)。
Action string
// Target 操作对象(如 app:<id>、node:<platform_id>)。
Target string
// Result 取 ok / error。
Result string
// ErrorCode 失败时的注册表错误码(可空)。
ErrorCode string
// RequestID 关联请求(可空)。
RequestID string
// DiffSummary diff 摘要(脱敏后的 JSON/文本,可空)。
DiffSummary string
}
AuditEntry 是一条审计记录。ID 可留空(自动生成 ULID);Actor/Action/ Result 为数据库级非空约束(audit_log 表 CHECK),写不出合法行即整事务 回滚——这是 fail-closed 的硬保证,包内不做宽松兜底。
type AuditRecord ¶
type AuditRecord struct {
ID string
At time.Time
Actor string
Action string
Target string
Result string
// ErrorCode 是失败路径的注册表错误码(” = 成功行)。
ErrorCode string
// DiffSummary 是审计差异摘要(” = 无)。
DiffSummary string
}
AuditRecord 是审计只读投影(验证/后台展示用)。T2.15 起随读通道披露 ErrorCode/DiffSummary(路由发布失败审计的断言面;加法扩展)。
type BackupWrite ¶
type BackupWrite struct {
// ID 留空自动生成 ULID(调用方需要目录名与台账 ID 一致时自行生成后
// 传入——Manager 先建目录后落账,传显式 ID)。
ID string
// At 落账时刻(零值取写入时刻)。
At time.Time
// Kind 必须是注册词表之一(unknown kind 直接报错——台账不接受不可归类
// 的行)。
Kind string
// Path / SHA256 / SizeBytes 是快照产物事实。
Path string
SHA256 string
Size int64
// Verify 必须是 verified / failed(pending 不可落账——落账即判定)。
Verify string
// Error 校验失败原因(failed 行必填)。
Error string
// AuditActor 审计 actor(默认 "system"——手动触发的行由 RPC 层传 token
// actor 形态,但备份本体恒为 daemon 执行,默认值覆盖全部自动路径)。
AuditActor string
}
BackupWrite 是一次备份的落账载荷(RecordStateBackup 消费)。
type BuildRecord ¶
type BuildRecord struct {
ID string
AppID string
Service string
Driver Driver
Status BuildStatus
ImageRef string
// ImageDigest 是不可变镜像 ID(`sha256:<hex>`);成功终态必非空(D9)。
ImageDigest string
// Request 是构建输入 JSON(构建队列的跨进程执行输入)。
Request string
// PlanPath / LogPath 是产物归档路径(railpack plan JSON / 构建日志)。
PlanPath string
LogPath string
// ErrorCode 是失败终态的注册表错误码。
ErrorCode string
CreatedAt time.Time
// StartedAt / FinishedAt:零值 = 未开始 / 未到终态。
StartedAt time.Time
FinishedAt time.Time
}
BuildRecord 是一次构建的权威记录行。
type BuildStatus ¶
type BuildStatus string
BuildStatus 是构建状态机的状态位。
const ( // BuildQueued 已入队待执行。 BuildQueued BuildStatus = "queued" // BuildBuilding 执行中。 BuildBuilding BuildStatus = "building" // BuildSucceeded 成功终态(image_digest 必非空)。 BuildSucceeded BuildStatus = "succeeded" // BuildFailed 失败终态(error_code 必非空)。 BuildFailed BuildStatus = "failed" )
type CachedNode ¶
type CachedNode struct {
SwarmNodeID string
Hostname string
State string
Availability string
IsManager bool
SubstrateVersion uint64
Labels map[string]string
// LastSeenAt 平台最近一次成功观测到该节点的时刻(观测语义,非底座
// 提供的时间戳)。
LastSeenAt time.Time
// ObservedAt 本行快照写入时刻(读契约字段)。
ObservedAt time.Time
// Stale 底座最近一次不可达时被整表置位;为真时本行内容可能是旧值,
// 禁止当事实消费(读契约字段)。
Stale bool
}
CachedNode 是 nodes 表行(观测缓存读投影)。
type DeployRecord ¶
type DeployRecord struct {
ID string
// AppID / AppName:app 外键与 compose 名(冗余快照便于跨进程渲染)。
AppID string
AppName string
// Kind ∈ deploy|rollback(00001 CHECK):仅已切流回滚建新记录(D-REL-7)。
Kind string
// Status 是状态机主状态;Phase 是子状态(blocked_waiting 或空)。
Status DeploymentStatus
Phase string
// RevisionID 是成功后固化的版本行(成功时回填;可空)。
RevisionID string
// RecoveryOf 是 rollback 记录指向的原 deployment(可空)。
RecoveryOf string
// SubstrateHalted:首发失败 scale=0 保留现场(场景 14)。
SubstrateHalted bool
// FirstHealthyAt 是切流判据(零值 = 未切流,D-REL-4)。
FirstHealthyAt time.Time
// Recovery / Verdict:同记录恢复记录与终态判定(可空)。
Recovery string
Verdict string
// ErrorCode 是失败终态的注册表错误码(可空)。
ErrorCode string
// 停机账(stop-first 如实累计)。
DowntimeMS int64
DowntimeStartedAt time.Time
DowntimeEndedAt time.Time
// 看门狗/观察窗时间标记(零值 = 未进入对应阶段)。
ReleaseStartedAt time.Time
WatchdogDeadlineAt time.Time
ObserveStartedAt time.Time
// PhaseStartedAt 是准备/构建预算基线(00009 加法列):queued → preparing
// 转换(引擎拾取)时刻——排队等待不计入预算(H11);零值(存量行未写)
// 时消费方回落 CreatedAt。releasing 由 ReleaseStartedAt 起算,两者互不
// 干扰。
PhaseStartedAt time.Time
// 期望态快照(spec_hash/env_snapshot_hash 明文哈希;desired_spec 为
// box envelope 密文,本层不解释)。
SpecHash string
EnvSnapshotHash string
DesiredHash string
DesiredSpec string
ComposePath string
// CancelRequested:CLI 置位、引擎消费(曾健康拒绝并清位)。
CancelRequested bool
// Flags 是部署级告警/标志位(bitmask;PostWindowAlerted /
// InstabilityWarning——L4 只告警一次与观察窗警告通过)。
Flags int64
// git 触发来源(T2.19 迁移 00007;空串 = API/CLI 直传 compose)。
SourceGitSHA string
SourceGitRef string
CreatedAt time.Time
UpdatedAt time.Time
}
DeployRecord 是一次部署的状态机行。
type DeploymentPatch ¶
type DeploymentPatch struct {
Status *DeploymentStatus
PrevStatus *DeploymentStatus // 非 nil 时作 from 谓词(CAS 推进)
Phase *string
RevisionID *string
SubstrateHalted *bool
FirstHealthyAt *time.Time
Recovery *string
Verdict *string
ErrorCode *string
DowntimeMS *int64
DowntimeStartedAt *time.Time
DowntimeEndedAt *time.Time
ReleaseStartedAt *time.Time
WatchdogDeadlineAt *time.Time
ObserveStartedAt *time.Time
PhaseStartedAt *time.Time
SpecHash *string
EnvSnapshotHash *string
DesiredHash *string
DesiredSpec *string
ComposePath *string
CancelRequested *bool
Flags *int64
SourceGitSHA *string
SourceGitRef *string
}
DeploymentPatch 是一次行更新承载的可选字段(零值 = 不写;时间字段用 指针区分「不写」与「清空」——NULL 语义字段才允许置回 NULL)。
type DeploymentStatus ¶
type DeploymentStatus string
DeploymentStatus 是发布状态机主状态(release-semantics §2.3)。
const ( // DeployQueued 已入队(同 app 互斥:等待在途部署终态)。 DeployQueued DeploymentStatus = "queued" // DeployPreparing 准备中(compose 重载/放置解析/env 合并/镜像 preflight)。 DeployPreparing DeploymentStatus = "preparing" // DeployBuilding 构建核对(build 层已完成则直通)。 DeployBuilding DeploymentStatus = "building" // DeployReleasing 发布中(Swarm service 对账 + 健康门;含 // blocked_waiting 子状态 = phase 列)。 DeployReleasing DeploymentStatus = "releasing" // DeployObserving 观察窗(默认 60s,只告警)。 DeployObserving DeploymentStatus = "observing" // DeploySucceeded 成功终态(观察窗通过;active revision 已前移)。 DeploySucceeded DeploymentStatus = "succeeded" // DeployFailed 失败终态(error_code 必非空;归位/分流结果在同记录)。 DeployFailed DeploymentStatus = "failed" // DeployCancelled 取消终态(先归位再落 cancelled)。 DeployCancelled DeploymentStatus = "cancelled" )
func AllDeploymentStatuses ¶
func AllDeploymentStatuses() []DeploymentStatus
AllDeploymentStatuses 返回主状态全词表(穷举测试遍历用)。
func LegalDeploymentTransitions ¶
func LegalDeploymentTransitions(from DeploymentStatus) []DeploymentStatus
LegalDeploymentTransitions 返回 from 的合法目标集合(穷举测试断言用; from 为终态或未知状态返回空)。
func (DeploymentStatus) Terminal ¶
func (s DeploymentStatus) Terminal() bool
Terminal 报告是否终态(succeeded/failed/cancelled)。
type DockerClient ¶
type DockerClient interface {
// Ping 探测底座可达性(观测缓存刷新的先决条件)。
Ping(ctx context.Context) error
// ListNodeObservations 返回全量节点观测快照(观测缓存 30s 全量 resync
// 的数据源,state-model §2.2)。底座不可达时返回错误,绝不返回部分
// 快照冒充全量。
ListNodeObservations(ctx context.Context) ([]SubstrateNode, error)
// SelfNodeID 返回本机 Swarm node ID;引擎未启用 Swarm 时返回
// ErrNotSwarmManager。
SelfNodeID(ctx context.Context) (string, error)
// UpdateNodeLabel 以乐观令牌更新节点 label(v0.1 唯一的 label 写入
// 接口,承载 node-id 身份锚;§2.4 最小 label 集,业务对象 label 下发
// 随 T2.14)。expected 与底座当前版本不符时返回 ErrVersionConflict;
// label 已是目标值时为幂等 no-op 并返回 nil。
UpdateNodeLabel(ctx context.Context, swarmNodeID, key, value string, expected ObjectVersion) error
// ResolveObjectVersion 直读底座对象版本(写前直读;对象缺失返回
// ErrObjectNotFound)。
ResolveObjectVersion(ctx context.Context, kind ObjectKind, id string) (ObjectVersion, error)
// SubscribeEvents 订阅底座事件流(node/service/task 变更作观测缓存的
// 失效信号,state-model §2.2;只作缓存失效信号,不作产品事件来源)。
// 返回的 channel 在 ctx 取消或流结束时关闭。
SubscribeEvents(ctx context.Context) (<-chan SubstrateEvent, error)
// Close 释放底层连接资源。
Close() error
}
DockerClient 是底座(Docker/Swarm)访问的小端口(架构 §2.8 Runtime 端口 的观测与身份子集,v0.1 切面)。核心(本包)只认识本文件定义的核心类型, 第三方类型只存在于适配器内部(internal/substrate,moby/client 实现)。
纪律:
- 方法返回的核心类型字段命名用平台语义,不透传底座结构;
- 底座对象版本(ObjectVersion)是写前直读的乐观令牌(state-model §2.2 读契约),适配器必须逐字取自底座对象版本,不得自造。
type Domain ¶
type Domain struct {
ID string
AppID string
Service string
Domain string
// Port 是路由目标端口(compose expose 首端口;” = 未同步)。
Port string
// CertSHA256 是证书 PEM(链 + 叶)内容 sha256 hex;” = 尚无证书。
CertSHA256 string
// CertNotAfter 是叶证书 NotAfter;零值 = 尚无证书。
CertNotAfter time.Time
// CertUpdatedAt 是证书登记最近一次写入;零值 = 从未。
CertUpdatedAt time.Time
// CreatedAt 是域名首 declarations 时间。
CreatedAt time.Time
}
Domain 是一条域名台账行。
type DomainServiceRoutes ¶
type DomainServiceRoutes struct {
Service string
// Port 是路由目标端口(compose expose 首端口)。
Port string
Domains []string
}
DomainServiceRoutes 是一次 per-service 域名声明(发布同步的输入单元)。
type Driver ¶
type Driver string
Driver 是构建驱动(与 compose 服务 build/image 两模式对应)。
const ( // DriverRailpack 无 build.dockerfile → Railpack 自动检出(钉版 v0.39.0, // internal/build)。 DriverRailpack Driver = "railpack" // DriverDockerfile 有 build.dockerfile → Dockerfile 前端(一等路径)。 DriverDockerfile Driver = "dockerfile" // DriverPassthrough 仅 image 模式直通(无构建;v0.1 不建行,枚举位预留)。 DriverPassthrough Driver = "passthrough" )
type EnvVar ¶
type EnvVar struct {
ID string
AppID string
Key string
Value string
Source string // platform | system(模板连接串留位,只读)
Status EnvVarStatus
CreatedAt time.Time
UpdatedAt time.Time
}
EnvVar 是平台层环境变量行(value 为调用方传入的存储形态——本层不解释 密文/明文,加密边界在 internal/secrets 与其调用方)。
type EnvVarStatus ¶
type EnvVarStatus string
EnvVarStatus 是 env_vars 生效状态位。
const ( // EnvStatusPending 已创建/更新但未部署消费(当前运行 env 不含它)。 EnvStatusPending EnvVarStatus = "pending" // EnvStatusEffective 已随部署生效(合并链可消费)。 EnvStatusEffective EnvVarStatus = "effective" )
type Event ¶
type Event struct {
Seq int64
At time.Time
Name string
Subject string
// Payload 是脱敏后的 JSON 文本(默认 "{}")。
Payload string
}
Event 是一条平台事件。Seq 由库分配(单调、删除后永不复用);Name 必须 是 eventcode 注册表内事件名(构造期纪律与 errcode 一致:非法名 panic)。
type GitKey ¶
type GitKey struct {
ID string
// Fingerprint 是公钥 SHA256 指纹("SHA256:<base64>")。
Fingerprint string
// PublicKey 是 authorized_keys 单行原文(公开材料,可回读)。
PublicKey string
// KeyType 是公钥类型词(ssh-ed25519 / ssh-rsa / ecdsa-sha2-nistp256…)。
KeyType string
// Note 是人读备注。
Note string
CreatedAt time.Time
}
GitKey 是一条平台管理的 git 公钥行(只读投影;平台从不接触私钥)。
type GitKeyWrite ¶
type GitKeyWrite struct {
// ID 留空自动生成 ULID。
ID string
// Fingerprint 必须非空(SHA256 指纹,调用方以 golang.org/x/crypto/ssh
// 的 FingerprintSHA256 计算后传入)。
Fingerprint string
// PublicKey 是 authorized_keys 单行原文。
PublicKey string
// KeyType 是公钥类型词。
KeyType string
// Note 是人读备注。
Note string
// ActorTokenID 是发起写入的调用方 token(审计 actor_token_id)。
ActorTokenID string
}
GitKeyWrite 是一次 git key 写入。
type Janitor ¶
type Janitor struct {
// contains filtered or unexported fields
}
Janitor 周期清理过期事件与审计记录(S18-A7/A10:外加部署目录/构建 台账/产物目录保留窗与非终态超龄扫描)。
func NewJanitor ¶
func NewJanitor(store *Store, cfg JanitorConfig, log *slog.Logger) *Janitor
NewJanitor 构造保留期清理守护。cfg 天数取非正值时回落默认(保留期是 契约默认,不允许被误配成 0 而静默关闭)。
func (*Janitor) AuditRetention ¶
func (*Janitor) EventRetention ¶
EventRetention / AuditRetention 返回生效保留期(诊断用)。
func (*Janitor) PruneOnce ¶
func (j *Janitor) PruneOnce(ctx context.Context, now time.Time) (events int64, audits int64, err error)
PruneOnce 执行一轮清理(now 为基准时刻),返回 (事件条数, 审计条数)。 独立导出供测试直接驱动。S18-A7/A10:一轮内顺次执行全部 duties—— 事件/审计分批删除 → builds 终态行 → 产物目录 → 部署 compose 目录 → 非终态超龄扫描;各 duty 失败独立记日志不中断后续(单 duty 失败不该 瘫痪整轮保留期治理),事件/审计错误仍向上返回(既有契约)。
type JanitorConfig ¶
type JanitorConfig struct {
// EventRetentionDays / AuditRetentionDays 是事件/审计保留天数。
EventRetentionDays int
AuditRetentionDays int
// BuildRetentionDays 是 builds 终态行保留天数(缺省 90)。
BuildRetentionDays int
// ArtifactsDir 是 build 产物归档根目录(build.artifacts_dir;空 = 跳过
// 目录清理——进程内测试夹具形态)。
ArtifactsDir string
// ArtifactsRetentionDays 是产物目录保留天数(缺省 30)。
ArtifactsRetentionDays int
// DeploymentsRoot 是部署 compose 持久化根(<数据根>/deployments;
// 空 = 跳过目录清理)。
DeploymentsRoot string
// DeploymentDirRetentionDays 是部署目录在终态后的保留天数(缺省 30)。
DeploymentDirRetentionDays int
// StaleDeploymentBudget 是部署非终态超龄判定预算(2×(DeployTimeout+
// ObserveWindow),装配自 engine 配置;≤0 跳过部署扫描)。
StaleDeploymentBudget time.Duration
// StaleBuildBudget 是构建非终态超龄判定预算(2×构建超时,装配自
// build 配置;≤0 跳过构建扫描)。
StaleBuildBudget time.Duration
}
JanitorConfig 是 janitor 的保留窗与预算参数集(S18-A7/A10 装配扩展: 构造参数从两个散装天数收口为结构体——新增 duties 的参数不再逐个膨胀 构造签名)。零值字段回落默认;目录/根为空时对应 duty 整体跳过。
type NodeIdentity ¶
type NodeIdentity struct {
// contains filtered or unexported fields
}
NodeIdentity 管理本机平台节点身份的生成、持久化与底座锚定。
func NewNodeIdentity ¶
func NewNodeIdentity(store *Store, d DockerClient, log *slog.Logger) *NodeIdentity
NewNodeIdentity 构造节点身份管理器。
func (*NodeIdentity) Anchor ¶
func (n *NodeIdentity) Anchor(ctx context.Context) error
Anchor 执行一次完整锚定:自省本机 Swarm node ID → 幂等写身份 label (写前直读取令牌 + 冲突重试)→ 登记 runtime_node_refs 映射(变更时 写系统审计)。引擎未启用 Swarm 返回 ErrNotSwarmManager(调用方退避 重试,例如安装流程 swarm init 完成前)。
func (*NodeIdentity) Anchored ¶
func (n *NodeIdentity) Anchored() bool
Anchored 报告身份是否已锚定到 Swarm 节点 label 并登记映射。
func (*NodeIdentity) CheckHealth ¶
func (n *NodeIdentity) CheckHealth() error
CheckHealth 报告身份就绪态:平台 ID 已生成即视为身份层健康(底座锚定 的健康语义由 observer 的底座检查承载,不在此重复——避免 swarm 未启用 的单机上身份检查拖垮 readiness)。
func (*NodeIdentity) EnsurePlatformID ¶
func (n *NodeIdentity) EnsurePlatformID(ctx context.Context) (string, error)
EnsurePlatformID 确保 meta 中存在本机平台节点 ID:缺失则生成 n_<ULID> 并与系统审计同事务落库(系统自动动作必入审计,state-model §2.9)。 幂等;返回平台节点 ID。
func (*NodeIdentity) PlatformID ¶
func (n *NodeIdentity) PlatformID() string
PlatformID 返回已确保的平台节点 ID(EnsurePlatformID 成功前为空串)。
type ObjectKind ¶
type ObjectKind string
ObjectKind 是写前直读的底座对象类别。
const ( // ObjectKindNode 是 Swarm 节点(id = swarm node ID)。 ObjectKindNode ObjectKind = "node" // ObjectKindService 是 Swarm 服务(id = swarm 服务名;平台名到底座名 // 的映射随 T2.14 适配器落地,本阶段令牌纪律先立)。 ObjectKindService ObjectKind = "service" )
type ObjectVersion ¶
type ObjectVersion struct {
Index uint64
}
ObjectVersion 是底座对象版本(乐观令牌)。Index 取自底座对象自身的 单调版本号,语义逐字镜像底座。
type Observer ¶
type Observer struct {
// contains filtered or unexported fields
}
Observer 维护 nodes 观测缓存。CheckHealth 结构性实现 lynx.Checker: 最近一次全量同步成功即健康。
func NewObserver ¶
func NewObserver(store *Store, d DockerClient, log *slog.Logger) *Observer
NewObserver 构造观测缓存刷新器。
func (*Observer) CheckHealth ¶
CheckHealth 实现 lynx.Checker:最近一次全量观测同步成功(含启动后的 首次同步)才健康;底座不可达 → 不健康(readiness 如实反映底座健康)。
func (*Observer) Invalidate ¶
func (o *Observer) Invalidate()
Invalidate 请求立即刷新(事件驱动失效信号入口;非阻塞,合并连发)。
type Placement ¶
type Placement struct {
AppID string
PlatformNodeID string
State PlacementState
Source PlacementSource
// LabelRef 是用户 label 书写原值(显示名或 n_<ULID>;空 = 未声明)。
LabelRef string
// Reason 是进入当前状态的派生原因(如 node_down / node_gone;可空)。
Reason string
// Etag 是绑定行乐观令牌(每次写重新生成)。
Etag string
// PinnedAt 首次钉住时刻(零值 = 未钉)。
PinnedAt time.Time
CreatedAt time.Time
UpdatedAt time.Time
}
Placement 是 placements 行(绑定记录投影)。
type PlacementSource ¶
type PlacementSource string
PlacementSource 是绑定来源词表。
const ( // PlacementSourcePlatform 平台自动选点(含首次自动绑定本机)。 PlacementSourcePlatform PlacementSource = "platform" // PlacementSourceLabel 用户 label 显式钉住(解析成功后落账)。 PlacementSourceLabel PlacementSource = "label" )
type PlacementState ¶
type PlacementState string
PlacementState 是绑定状态位(00001 词表)。
const ( // PlacementBound 已绑定(设计文档的 ok 态)。 PlacementBound PlacementState = "bound" // PlacementBlocked 绑定节点不可用/已移除,应用 blocked。 PlacementBlocked PlacementState = "blocked" // PlacementUnresolved DR 后绑定无法判定,要求显式放置(不猜测)。 PlacementUnresolved PlacementState = "unresolved" )
type PlacementWrite ¶
type PlacementWrite struct {
AppID string
PlatformNodeID string
State PlacementState
Source PlacementSource
LabelRef string
Reason string
ExpectedEtag string
// Pinned 首次钉住时置位(pinned_at 取写入时刻;已有值保持不动)。
Pinned bool
}
PlacementWrite 是一次绑定写入:ExpectedEtag 非空时为 CAS(compare-and- swap,令牌不符 → ErrVersionConflict);空 = 无条件 upsert(首次绑定)。
type Revision ¶
type Revision struct {
ID string
AppID string
Seq int64
ComposeNormalized string
Overlay string
DesiredHash string
Verified bool
// Status 是保留窗状态位(active = 可回滚选项;superseded = 被保留窗
// 淘汰,仅存档——列表即选项,列不出来的不可回滚)。
Status string
CreatedAt time.Time
}
Revision 是一次版本快照行。
type RevisionWrite ¶
type RevisionWrite struct {
// ID 留空自动生成 ULID。
ID string
AppID string
ComposeNormalized string
Overlay string
DesiredHash string
}
RevisionWrite 是一次版本快照写入。
type RuntimeNodeRef ¶
type RuntimeNodeRef struct {
PlatformID string
SwarmNodeID string
CreatedAt time.Time
UpdatedAt time.Time
AnchoredAt time.Time
}
RuntimeNodeRef 是适配器映射行。
type SourceAuthKind ¶
type SourceAuthKind string
SourceAuthKind 是 webhook 拉源认证形态词表。
const ( // SourceAuthNone 匿名拉取(file:// / 公开 https 仓库)。 SourceAuthNone SourceAuthKind = "none" // SourceAuthToken HTTPS + token(http.extraHeader 形态注入)。 SourceAuthToken SourceAuthKind = "https_token" // SourceAuthSSHKey SSH 私钥(GIT_SSH_COMMAND 临时密钥文件注入)。 SourceAuthSSHKey SourceAuthKind = "ssh_key" )
type StateBackup ¶
type StateBackup struct {
// ID 记录 ID(ULID;与备份目录名一致——<backup.dir>/<ID>/fleetly.db)。
ID string
// Kind 触发类别:daily / pre_upgrade / post_deploy / manual(历史行可为
// hot/cold——00008 之前的占位枚举)。
Kind string
// Path 是快照文件路径(manifest.json 与其同目录)。
Path string
// SHA256 是快照文件的 sha256(hex;回读校验对象)。
SHA256 string
// SizeBytes 是快照文件字节数。
SizeBytes int64
// VerifyStatus 是回读校验结论:verified / failed(pending = 落账时未校验,
// 现行写入路径不会产生——校验先于落账,唯一诚实态是已判定)。
VerifyStatus string
// Error 是校验失败原因原文(verified 行为空)。
Error string
// CreatedAt 是台账落账时刻(UTC)。
CreatedAt time.Time
}
StateBackup 是 state_backups 台账行的只读投影。
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store 是控制面状态层门面:SQLite 权威态存储 + 底座观测缓存写入 + 写前直读端口消费。零框架依赖——lynx.Service/Checker 装配壳在 cmd/fleetlyd(CheckHealth 为结构性实现,进 healthz readiness)。
func Open ¶
Open 打开(必要时创建)状态库并应用全部迁移:启动即建库迁移、失败 fail-fast 拒绝启动。path 为数据库文件路径(默认 ./fleetly.db,由 config state.db_path 提供)。
func (*Store) AppHasNonTerminalDeployment ¶
AppHasNonTerminalDeployment 报告应用是否存在在途部署(同 app 互斥)。
func (*Store) AuthenticateToken ¶
AuthenticateToken 按明文认证:哈希查行 → 常量时间二次比对(belt-and- suspenders:行查找按哈希等值走索引,不泄漏明文时序;二次比对保证比对 通道本身常量时间)→ 吊销检查。成功返回在册 token。**不盖 last_used_at** (S18-A2:每请求同步写是 SQLite 写放大——盖写职责上移到调用方 internal/api 的认证路径,经进程内节流后调 TouchTokenUsed),本层保持 纯认证语义。
func (*Store) BindPlacement ¶
BindPlacement 写入绑定(无条件 upsert,etag 重新生成)。CAS 语义见 PlacementWrite.ExpectedEtag;pinned_at 只在首次置位、此后保持(数据诞生 点叙事),显式换点不洗掉历史钉住时刻。
func (*Store) CheckHealth ¶
CheckHealth 实现 lynx.Checker(结构性满足,本包不 import 框架): 数据库可达即健康。检查自带 2s 上限(readiness 探测挂死防护由框架 另有 3s 兜底,此处自查优先快速失败)。
func (*Store) ClaimBuild ¶
ClaimBuild 原子认领:queued → building(started_at 盖章),审计 build.start 同事务。ErrBuildStateTransition 表示已被认领/终态(多 worker/ 重复扫描竞争的安全路径——行级谓词保证恰好一个 claimer 胜出)。
func (*Store) CountGitDeploymentsForSHA ¶
CountGitDeploymentsForSHA 统计应用在给定 git commit 上处于 enqueued/ active/succeeded 的部署数(T2.19 webhook 幂等去重判据:> 0 = 该 sha 已有 进行中或成功的部署,重投不建新记录;failed/cancelled 不计入——失败后重投 应允许重试)。source_git_sha 为空串的部署(API/CLI 直传)不参与匹配。
func (*Store) CreateApp ¶
CreateApp 创建应用行(active)。同名(任意生命周期态)返回 ErrAppExists——deleted 名字在保留期内不释放,不复活、也不顶替。 appID 留空自动生成 ULID。
func (*Store) CreateBuild ¶
func (s *Store) CreateBuild(ctx context.Context, rec BuildRecord) (BuildRecord, error)
CreateBuild 创建 queued 构建记录(构建入队;id 留空自动生成 ULID)。 审计 build.create 与建行同事务(fail-closed),归因固定 system(内部 队列/复位路径)。调用方触发(API TriggerBuild)的归因见 CreateBuildAs。
func (*Store) CreateBuildAs ¶
func (s *Store) CreateBuildAs(ctx context.Context, rec BuildRecord, audit *AuditEntry) (BuildRecord, error)
CreateBuildAs 是 CreateBuild 的审计归因扩展(M4-8):audit 非 nil 时 build.create 审计行由调用方注入——TriggerBuild 的入队审计带调用方 token(H14 敏感写面:base_dir 可指宿主任意目录,行为人必须可追溯); nil 时回落 CreateBuild 既有 system 归因(与旧行为逐字一致)。建行与 审计仍同事务 fail-closed。
func (*Store) CreateDeployment ¶
func (s *Store) CreateDeployment(ctx context.Context, rec DeployRecord) (DeployRecord, error)
CreateDeployment 创建 queued 部署行(发布入队;独立事务薄壳,兼容既有 调用方与测试夹具)。kind 取 deploy|rollback。部署入队需要事件/审计 fail-closed 同事务(state-model §2.9,H13)的调用方必须改用 Store.InTx + Tx.CreateDeployment 组合——本壳内的事件/审计无从共享事务。
func (*Store) CreateGitKey ¶
CreateGitKey 落一条 git key 行并与审计(gitkey.add)同事务 fail-closed。 同指纹重复注册返回 ErrGitKeyExists。
func (*Store) CreateToken ¶
CreateToken 在事务内落一条 token 行(哈希形态入参)并与审计同事务 fail-closed。
func (*Store) DeleteAppDomains ¶
DeleteAppDomains 删除应用的全部域名台账行(应用移除/路由撤销时调用; 幂等)。
func (*Store) DeleteAppEnv ¶
DeleteAppEnv 删除单条 env(幂等:键不存在返回 ErrEnvNotFound)。审计同 事务 fail-closed,摘要只含键名。
func (*Store) DeleteStateBackup ¶
DeleteStateBackup 删除一行台账(保留期清理用;与 backup.pruned 审计同 事务——删账必留痕)。返回删除行的 path(调用方负责目录清除)。
func (*Store) EnterPhase ¶
func (s *Store) EnterPhase(ctx context.Context, id string, from, to DeploymentStatus, extra DeploymentPatch, events ...Event) error
EnterPhase 是部署状态转换的单一写点(v0.2 T0-V2.2,设计出处:评审报告 类 A 补齐①/整改方案 §9 挂账项「EnterPhase 全量单写点」)。同一事务内 完成四件事:
- 转移合法性校验:CanTransitionDeployment(from, to),表外组合拒写并 返回 ErrIllegalTransition(语义与 S16-C5 逐字一致);
- status/phase/error 等伴随字段写入:extra 补丁承载(ReleaseStartedAt/ WatchdogDeadlineAt/ErrorCode/Verdict/RevisionID/Recovery…),与 CAS 一并原子生效(复用 updateDeployment 内核——终态不可逆守卫与 RowsAffected 竞争裁决语义不变);extra 不得携带 Status/PrevStatus (转换边由 from/to 参数权威给出,双源即编码错误);
- 计时相位锚点:queued → preparing(引擎拾取边)必须携带 extra.PhaseStartedAt = 拾取时刻(S9/H11:预算自拾取起算、排队等待 不计入;时间戳由调用方时钟提供——引擎单测的假时钟下写点自取墙钟 会错位预算基准)。缺锚即拒:锚点漏写/误用因单写点不可发生。其余 边不刷新锚点——准备+构建共用拾取基线(preparing→building 刷新即 私自续预算)、releasing 由 watchdog_deadline_at 起算,两者互不干扰;
- 既有事件追加:events 逐条经 Tx.AppendEvent(eventcode 注册表校验) 写入同一事务(Outbox,state-model §2.9)——转换落库与事件披露原子; 只允许既有事件码(不新增);CAS 落败(RowsAffected=0)时事务回滚、 不产生任何事件。
Store 形态 = 独立事务薄壳(独立转换调用方);需要把转换与 revision 固化、 审计等业务写组合在同一事务的调用方(成功终态、回滚失败终态——S18-A6) 使用 Tx 形态嵌入既有 InTx。
func (*Store) EventsSince ¶
EventsSince 返回 seq > since 的事件(升序,至多 limit 条)。游标早于 保留窗((since, oldest_seq) 区间的事件已被清理)时返回 *apperr.Error{code: E_EVENT_CURSOR_EXPIRED}(HTTP 410),context 携带 oldest_seq——显式断档,调用方(SSE/列表)应从 oldest_seq 重新拉全量。
func (*Store) FailStrandedBuild ¶
FailStrandedBuild 把单条 building 行收敛为 failed 终态(队列侧兜底:执行 器返回后行仍停留 building——超时取消后未收敛、异常退出等路径)。CAS building→failed + finished_at 盖章 + error_code,审计 build.finish (result=error)同事务;reason 进审计 diff(builds 表只存注册表 error_code,兜底上下文——超时预算/中断原因——的可观测落点在审计)。
func (*Store) FindBuildsByDigest ¶
FindBuildsByDigest 按不可变镜像 ID 反查登记(digest→ref 映射读通道, T2.9 镜像身份;返回含该 digest 的全部成功构建行)。
func (*Store) FinishBuildFailed ¶
FinishBuildFailed 推进 building → failed 并落注册表错误码;审计 build.finish(result=error)同事务。
func (*Store) FinishBuildSucceeded ¶
func (s *Store) FinishBuildSucceeded(ctx context.Context, id, imageRef, imageDigest, planPath, logPath string) error
FinishBuildSucceeded 推进 building → succeeded 并落镜像身份(ref + 不可变 digest,D9)。终态谓词防重复收敛;审计 build.finish 同事务。
func (*Store) GetAppByID ¶
GetAppByID 按平台 ID 取应用行;不存在返回 ErrAppNotFound(入口路由 合成时的 app 名反查消费)。
func (*Store) GetAppByName ¶
GetAppByName 按名取应用行;不存在返回 ErrAppNotFound。
func (*Store) GetAppDerivedState ¶
GetAppDerivedState 读派生状态缓存(空串 = 尚未推导,读面按派生规则即时 计算的语义归调用方)。
func (*Store) GetAppDriftConverge ¶
GetAppDriftConverge 读取漂移自动收敛 opt-in 位(apps.drift_converge, 00005 加法列)。默认关(D11:检测默认开、自动收敛默认关)——列不存在 语义即关,false 是唯一安全缺省。回滚失败时引擎强制清 0(D-REL-10), 人工经 CLI 重新置位(带审计)。
func (*Store) GetAppGitConfig ¶
GetAppGitConfig 读 app git 触发配置(appID 必须存在——不存在返回 ErrAppNotFound)。
func (*Store) GetAppRevision ¶
GetAppRevision 解析该 app 的一个可回滚目标(active + app 归属双谓词); 不存在 / 已被保留窗淘汰 / 归属不符 → ErrRevisionNotFound(列表即选项: 列不出来的不可回滚)。
func (*Store) GetAppVolume ¶
GetAppVolume 取单卷;不存在返回 ErrVolumeNotFound。
func (*Store) GetDeployment ¶
GetDeployment 按ID取部署行;不存在返回 ErrDeploymentNotFound。
func (*Store) GetGitKeyByFingerprint ¶
GetGitKeyByFingerprint 按指纹取 key 行(SSH publickey 回调的认证查点); 不存在返回 ErrGitKeyNotFound。
func (*Store) GetPlacement ¶
GetPlacement 取绑定记录;无记录返回 ErrPlacementNotFound。
func (*Store) GetRevision ¶
GetRevision 按 ID 取版本快照(不限保留窗状态——存档行仍可读);不存在 返回 ErrRevisionNotFound。回滚目标解析须走 GetAppRevision(active 谓词)。
func (*Store) GetRuntimeNodeRef ¶
GetRuntimeNodeRef 返回映射行(未锚定返回 ErrRefNotFound)。
func (*Store) HasAnyToken ¶
HasAnyToken 报告是否已存在任意 token 行(含已吊销)——bootstrap 判定 「首启无任何 token」的谓词(吊销过的也算存在过:bootstrap 一次性语义)。
func (*Store) InTx ¶
InTx 在单个写事务内执行 fn:事务以 BEGIN IMMEDIATE 开启(见 dsn), fn 返回错误或 panic 均回滚(panic 回滚后原样重抛,不吞栈)——审计/ 事件与业务写共享同一事务即由此组合(fail-closed)。
func (*Store) LatestDeploymentsByApp ¶
func (s *Store) LatestDeploymentsByApp(ctx context.Context, appIDs []string, perApp int) (map[string][]DeployRecord, error)
LatestDeploymentsByApp 批量返回一组应用各自的最近部署窗口(每 app 至多 perApp 条,created_at 倒序——与逐 app 调 ListAppDeployments 同序同窗)。 S18-A4:ListApps 派生状态的 N+1 收口——N 个 app 的派生输入从 N 次 per-app 查询并为一次 IN 查询(窗口截断经 ROW_NUMBER,不拉全量行)。 空 appIDs 直接返回空 map(不发 SQL);map 中不出现的键 = 该 app 无 部署记录。
func (*Store) LatestStateBackup ¶
func (s *Store) LatestStateBackup(ctx context.Context) (*StateBackup, error)
LatestStateBackup 返回最近一条台账(无备份记录 → nil, nil——调用方据此 表达「从未成功备份」的不健康态,不谎报)。
func (*Store) ListActiveApps ¶
ListActiveApps 返回全部 active 应用(created_at 升序;引擎运行期巡检的 候选集,v0.1 单机规模)。
func (*Store) ListAllDomains ¶
ListAllDomains 返回全部域名台账行(app_id, domain 字典序;全量配置 合成的事实源)。
func (*Store) ListAppBuilds ¶
ListAppBuilds 按应用返回构建记录(created_at 倒序,至多 limit 条; limit ≤ 0 取默认 50)。
func (*Store) ListAppDeployments ¶
func (s *Store) ListAppDeployments(ctx context.Context, appID string, limit int) ([]DeployRecord, error)
ListAppDeployments 按应用返回部署记录(created_at 倒序,至多 limit 条)。
func (*Store) ListAppDomains ¶
ListAppDomains 返回应用的域名台账行(domain 字典序)。
func (*Store) ListAppEnv ¶
ListAppEnv 返回该 app 全部 env 行(含 pending,按 key 字典序)。消费面 三处:发布引擎合并链(pending 参与合并——部署即消费点,S16-C4)、CLI/ API 展示(键名/来源/状态位投影)、日志脱敏值集(pending 值同样不得进 日志)。
func (*Store) ListAppVolumes ¶
ListAppVolumes 返回该 app 全部卷(按 key 字典序)。
func (*Store) ListAppsByLifecycle ¶
ListAppsByLifecycle 返回指定生命周期状态位的全部应用(created_at 升序; H10/MG-3:引擎 deleting 回收 duty 的候选集查询——tombstone 第二拍的 执行者据此发现待收敛应用)。lifecycle 必须是 AppLifecycle 词表值, 调用方(引擎 duty)直接传常量,本函数不做词表校验(空集 = 无待收敛)。
func (*Store) ListCachedNodes ¶
func (s *Store) ListCachedNodes(ctx context.Context) ([]CachedNode, error)
ListCachedNodes 返回全部观测缓存行(按 swarm_node_id 字典序)。 展示/诊断专用:决策路径禁用(见包注释与 state-model §2.2)。
func (*Store) ListGitKeys ¶
ListGitKeys 返回全部在册 git key(created_at 升序)。
func (*Store) ListNonTerminalBuilds ¶
func (s *Store) ListNonTerminalBuilds(ctx context.Context) ([]BuildRecord, error)
ListNonTerminalBuilds 返回全部非终态构建行(S18-A10:janitor 非终态超龄 扫描的输入——正常态由队列 worker 认领/收敛,超龄停留即状态机漏洞的显性 化告警;只读不自愈)。queued 行基线 created_at,building 行基线 started_at。
func (*Store) ListNonTerminalDeployments ¶
func (s *Store) ListNonTerminalDeployments(ctx context.Context) ([]DeployRecord, error)
ListNonTerminalDeployments 返回全部非终态部署(重启恢复扫描)。
func (*Store) ListRevisions ¶
ListRevisions 返回该 app 保留窗内的版本快照(active,seq 降序 = 最新 在前,release-semantics §2.4「列表即选项」——返回集即可回滚目标全集)。
func (*Store) ListStateBackups ¶
ListStateBackups 按 created_at 倒序返回最近 n 条台账(n<=0 = 全部—— 台账量级 = 保留份数 + 失败行,天花板低)。
func (*Store) ListTokens ¶
ListTokens 返回全部在册(未吊销)token(created_at 升序)。
func (*Store) MarkAllNodesStale ¶
MarkAllNodesStale 将全部缓存行置 stale=1(底座不可达的降级读契约: 内容可能是旧值),observed_at/last_seen_at 不动(仍指最后一次真实 观测)。无行时为 no-op。
func (*Store) MarkAppDeleted ¶
MarkAppDeleted 推进 deleting → deleted(tombstone 第二拍)。仅允许从 deleting 出发——active 直达 deleted 被拒绝(状态机纪律,防跳过清理)。
func (*Store) MarkAppDeleting ¶
MarkAppDeleting 推进 active → deleting(tombstone 第一拍)。仅允许从 active 出发;deleting/deleted 重复进入返回 ErrInvalidLifecycleTransition。
func (*Store) MarkAppEnvEffective ¶
MarkAppEnvEffective 把该 app 全部 pending 行提升为 effective(部署成功 终态后的消费点,observing.go succeedDeployment 在 env 注入并成功后调用; kind=rollback 不提升——重放的 env 随快照,pending 未被本次部署消费), 返回提升行数。幂等。
func (*Store) MarkAppVolumesOrphaned ¶
MarkAppVolumesOrphaned 把该 app 全部 active 卷置 orphaned(应用删除默认 保留卷语义;调用方在 tombstone 流程触发)。返回置孤儿卷数。幂等。
func (*Store) NextQueuedBuilds ¶
NextQueuedBuilds 返回最早入队的至多 limit 条 queued 记录(FIFO 排队语义, 队列 worker 的候选扫描;claim 由 ClaimBuild 原子完成)。
func (*Store) NextQueuedDeployments ¶
NextQueuedDeployments 返回最早入队的至多 limit 条 queued 记录(FIFO)。
func (*Store) PlacementByApp ¶
PlacementByApp 批量取一组应用的绑定记录。S18-A4:ListApps 派生状态的 N+1 收口——N 个 app 的绑定从 N 次 GetPlacement 并为一次 IN 查询。 空 appIDs 直接返回空 map(不发 SQL);map 中不出现的键 = 该 app 无 绑定记录(ErrPlacementNotFound 的批量等价形态——无绑定是合法运行态, 不以错误表达)。
func (*Store) PruneExpiredAudits ¶
PruneExpiredAudits 删除早于 cutoff 的审计记录,返回清理条数 (审计保留期默认 1 年,state-model §2.9)。分批形态同 PruneExpiredEvents。
func (*Store) PruneExpiredEvents ¶
PruneExpiredEvents 删除早于 cutoff 的事件,返回清理条数(保留期清理 job 的执行体;job 编排在 janitor.go)。S18-A10:分批循环删除(子查询 限定每批 500 行——modernc SQLite 不支持 DELETE...LIMIT 语法,子查询形态 承载批量语义)。
func (*Store) PruneTerminalBuildsOlderThan ¶
PruneTerminalBuildsOlderThan 分批删除终态早于 cutoff 的构建行(S18-A10: builds 台账 90 天保留窗;finished_at 是终态时刻,零值行不删——防御存量 脏数据)。分批形态与事件/审计清理一致(见 PruneExpiredEvents)。
func (*Store) RecentAudits ¶
RecentAudits 按 at 倒序返回最近 n 条审计记录。
func (*Store) RecordStateBackup ¶
func (s *Store) RecordStateBackup(ctx context.Context, w BackupWrite) (StateBackup, error)
RecordStateBackup 落一行备份台账(与审计同事务,fail-closed:审计写不出 合法行则台账行一并回滚——备份账与审计账互为证据)。kind/verify 词表 校验在此收口,非法值整单拒绝。
func (*Store) RegisterAppVolume ¶
RegisterAppVolume 登记卷(重新声明转 active——孤儿卷被应用重新声明即 复活;数据不随声明删除,name/node 等事实字段以最新声明为准)。created_at 首次落账后保持(防代际静默复用的叙事锚)。返回 isNew:首次登记为 true (调用方据此发 volume.created 事件——数据诞生点)。
func (*Store) RemoveGitKey ¶
RemoveGitKey 物理删除一条 git key(历史在审计可查)并与审计(gitkey. remove)同事务 fail-closed;不存在返回 ErrGitKeyNotFound。
func (*Store) ReplaceAppDomains ¶
func (s *Store) ReplaceAppDomains(ctx context.Context, appID string, declared []DomainServiceRoutes) error
ReplaceAppDomains 把应用的域名台账对账到声明集(发布同步语义, architecture §2.4 域名行):声明集内逐域名 upsert(归属 service/端口变更 即改写),台账中声明集之外的本应用行删除。幂等;单一写事务(fail-closed)。
func (*Store) ResetInterruptedBuilds ¶
ResetInterruptedBuilds 复位全部 building 行为 failed 终态并返回实际复位 行数(daemon 启动恢复:崩溃/关停时在途构建无人收敛——NextQueuedBuilds 只扫 queued,遗留 building 行永不重跑,等它的部署在引擎侧空转到发布 超时)。逐行经 FailStrandedBuild 的 CAS building→failed(行级谓词,与 ClaimBuild 同款竞争语义:复位时行已被并发收敛/已终态则跳过不误伤), finished_at 盖章、审计 build.finish 逐行同事务;reason 进审计 diff。 queued 行不动(本方法只扫 building;重启后队列自然重扫认领)。
func (*Store) RevokeToken ¶
RevokeToken 吊销 token(幂等:已吊销返回成功;不存在返回 ErrTokenNotFound)。与审计同事务 fail-closed。
func (*Store) RevokeTokenGuardLastAdmin ¶
func (s *Store) RevokeTokenGuardLastAdmin(ctx context.Context, id, actorTokenID string, isAdmin func(scopes string) bool) error
RevokeTokenGuardLastAdmin 是带最后管理员守卫的吊销(M4-6):吊销生效后 仍须存在 ≥1 枚未吊销 admin token,否则整笔回滚返回 ErrTokenLastAdmin (幂等面与 RevokeToken 一致:目标已吊销 = 幂等成功,不触发守卫——没有 新的吊销发生;不存在仍 ErrTokenNotFound)。守卫判定与吊销在同一事务内 (先 UPDATE 再复查剩余在册行,不满足即返回错误回滚),消除「检查与吊销 分离」的竞态窗。isAdmin 由调用方注入(scope 蕴含判定 admin ⊃ deploy ⊃ read 属 api 层语义,本层不解释 scopes 词表——本层只提供原子性)。
func (*Store) SchemaVersion ¶
SchemaVersion 返回已应用迁移版本(goose 版本表最大 version_id;manifest 的 schema_version 字段来源)。空库不该发生(Open 即迁移),查询失败照 实上抛。
func (*Store) SetAppEnv ¶
SetAppEnv 创建或更新平台 env(同 app 同 key 唯一):写值并把 status 重置 为 pending(既有 effective 行被覆盖同样回到 pending——生效语义 = 下次部署 消费)。审计同事务 fail-closed,diff 摘要只含键名与状态,不含值。 source 取 platform / system;留空回落 platform。
func (*Store) SetAppSource ¶
SetAppSource 写入拉源配置(branch 同步承载 push 触发分支语义)。与审计 (app.source_set)同事务 fail-closed。
func (*Store) SetAppWebhookSecret ¶
func (s *Store) SetAppWebhookSecret(ctx context.Context, appID, ciphertext, actorTokenID string) error
SetAppWebhookSecret 设置/清除 webhook 签名密钥(ciphertext 为 envelope 密文;空串 = 清除,端点回到未启用语义)。与审计(app.webhook_secret_set) 同事务 fail-closed;动作可能是清除——diff 如实记录 set/clear。
func (*Store) SetBuildLogPath ¶
SetBuildLogPath 回填 building 行的 log_path(M2-5:构建产物目录就位即写 ——log_path 原先唯一写点在 FinishBuildSucceeded,失败终态行恒空,失败 取证(日志尾部 + log_path context)落空)。行级谓词限定 building:终态 行不动(成功终态的 log_path 由 FinishBuildSucceeded 权威写入);0 行更新 (行已终态/不存在)静默成功——回填是 best-effort 观测面而非状态机事件, 无审计、不因竞态报错。
func (*Store) SetDomainCert ¶
func (s *Store) SetDomainCert(ctx context.Context, appID, domain, certSHA256 string, notAfter time.Time) error
SetDomainCert 登记证书材料(sha256 + 叶到期时间;同事务刷新登记时间)。 未命中(域名已被同步删除)返回 ErrDomainNotFound——签发晚于域名撤销的 竞态安全路径。
func (*Store) SyncNodeObservations ¶
func (s *Store) SyncNodeObservations(ctx context.Context, nodes []SubstrateNode, at time.Time) error
SyncNodeObservations 全量写入一拍观测快照:upsert 全部节点(observed_at = at、stale 清零、last_seen_at 取 max(旧值, at))并在同事务内修剪快照 中已消失的节点行(缓存可整表重建,消失即删;节点下线叙事属 events 表 历史,产品事件随后续票接入)。
func (*Store) TerminalDeploymentIDsOlderThan ¶
func (s *Store) TerminalDeploymentIDsOlderThan(ctx context.Context, cutoff time.Time) (map[string]bool, error)
TerminalDeploymentIDsOlderThan 返回终态早于 cutoff 的部署 ID 集合 (S18-A7:janitor 按「终态后 30 天窗」清理 deployments/<id>/ compose 持久化目录的判据来源;updated_at 是终态写入时刻的最近似代理——终态 不可逆,终态行此后只有 flag 类就地更新)。单查询全量返回,janitor 周期 (小时级)消费。
func (*Store) TouchTokenUsed ¶
TouchTokenUsed 刷新 last_used_at(尽力而为观测面;token 已消失时静默)。
func (*Store) UpdateDeployment ¶
UpdateDeployment 按补丁更新部署行。PrevStatus 非 nil 时为 CAS 迁移 (当前状态 ≠ PrevStatus → ErrDeploymentStateTransition,RowsAffected=0), 且**先经转移表校验** PrevStatus → Status 合法(S16-C5:表外组合是确定性 编码错误,拒写返回 ErrIllegalTransition——即使当前行恰好仍是 from 状态 也不落库);携带 Status 而 PrevStatus 为 nil 时拒绝(M3-2:状态写必须 带 from 谓词,引擎单写点纪律);两者皆 nil 时不带状态谓词(子状态/时间 锚/告警位等就地更新,仅受终态不可逆守卫)。updated_at 恒重盖。同一补丁 内 Status 与字段一并原子生效。
func (*Store) UpsertRuntimeNodeRef ¶
func (s *Store) UpsertRuntimeNodeRef(ctx context.Context, platformID, swarmNodeID string, anchoredAt time.Time) (bool, error)
UpsertRuntimeNodeRef 维护平台节点 ID ↔ Swarm node ID 适配器映射 (state-model §2.3:映射本身可从节点 label 反建;身份 label 被删改后 对账器自动重放的依据)。返回是否发生了变更(供调用方决定是否审计)。 同一 swarm_node_id 换绑到新 platform_id 视为换机/重建,拒绝并返回 ErrVersionConflict 复用冲突语义(重绑走人工 rebind,平台不猜测)。
type SubstrateEvent ¶
SubstrateEvent 是一次底座事件(仅作观测缓存失效信号)。
type SubstrateNode ¶
type SubstrateNode struct {
// SwarmNodeID 是底座节点 ID(runtime_node_refs 映射的键)。
SwarmNodeID string
// Hostname 是底座节点主机名(显示名)。
Hostname string
// State 是底座节点状态(ready/down/disconnected/unknown 逐字镜像)。
State string
// Availability 是底座节点可用性(active/pause/drain 逐字镜像)。
Availability string
// IsManager 报告该节点是否承担 manager 角色。
IsManager bool
// Version 是底座节点对象版本(节点 label 写入的乐观令牌)。
Version ObjectVersion
// Labels 是节点全部 label(含 fleetly.node-id 身份锚)。
Labels map[string]string
}
SubstrateNode 是一次节点观测快照(nodes 表行来源)。State/Availability 逐字镜像底座(平台不制造节点健康语义,state-model §2.3)。
type Token ¶
type Token struct {
ID string
// TokenHash 是明文 token 的 sha256 hex(64 字符)。
TokenHash string
// Name 是人读备注(proto 面 note;建行时落)。
Name string
// Scopes 是逗号分隔 scope 词表(如 "read,deploy")。
Scopes string
// HashPrefix 是 TokenHash 前 12 hex(识别用,非凭据)。
HashPrefix string
CreatedAt time.Time
// LastUsedAt 零值 = 从未使用。
LastUsedAt time.Time
// RevokedAt 零值 = 在册。
RevokedAt time.Time
}
Token 是一条 API token 行(只读投影;明文不存在于任何通道)。
type TokenWrite ¶
type TokenWrite struct {
// ID 留空自动生成 ULID。
ID string
// Hash 必须是 HashToken 产物形态(64 hex sha256);非法形态拒绝
//(防御性,防旁路写入明文)。
Hash string
// Name 是人读备注(proto 面 note)。
Name string
// Scopes 是逗号分隔 scope 词表(调用方已归一,如 "read,deploy")。
Scopes string
// ActorTokenID 是发起写入的调用方 token(可空——bootstrap 种子无调用
// 方 token);入审计 fail-closed。
ActorTokenID string
// Actor 是审计主体(human/ai_agent/system;空回落 human——系统代签发
// 的 token 如 git push 钩子回调 token 传 system,T2.19)。
Actor string
}
TokenWrite 是一次 token 写入。
type Tx ¶
Tx 是写事务句柄:业务写 + 审计 + 事件在同一事务内组合。
func (*Tx) AppendEvent ¶
AppendEvent 在事务内追加事件并返回分配的 seq:AUTOINCREMENT 保证 seq 严格单调且被保留期清理删除后不复用(sqlite_sequence 记录历史最大值), SSE 游标语义因此可依赖「seq 不回退、不断号不透明化」——断档必须经 E_EVENT_CURSOR_EXPIRED 显式暴露。与业务写同事务 = Outbox 模式。
func (*Tx) BindPlacement ¶
BindPlacement 是事务内绑定写(供与审计/事件同事务组合)。
func (*Tx) CountGitDeploymentsForSHA ¶
CountGitDeploymentsForSHA 是事务内的同口径复查(M3-4:webhook sha 幂等 去重的竞态闭合——COUNT 与 INSERT 必须同事务。Store 层各事务以 BEGIN IMMEDIATE 起手取写锁(见 store.go dsn),两路并发同 sha 入队在写锁上 串行化,后到事务的 COUNT 必然看到先行事务已提交的行 → 返回 ErrDuplicateGitDeployment 判据由调用方在建行前消费)。词法口径与 Store.CountGitDeploymentsForSHA 逐字一致。
func (*Tx) CreateBuild ¶
func (t *Tx) CreateBuild(ctx context.Context, rec BuildRecord) (BuildRecord, error)
CreateBuild 是事务内创建 queued 构建记录。
func (*Tx) CreateDeployment ¶
func (t *Tx) CreateDeployment(ctx context.Context, rec DeployRecord) (DeployRecord, error)
CreateDeployment 在事务内创建 queued 部署行(发布入队原语,H13)。 fail-closed 语义:入队调用方应把本 INSERT 与 deployment 事件、审计写在 同一 InTx 回调内——回调内任一写失败(含事件/审计写失败)即整体回滚, 部署行不落库,杜绝「部署行已存在、引擎照常执行但事件与审计缺失」的 审计黑洞。kind 取 deploy|rollback(校验在此层);actor 语义在调用方 (CLI=human、引擎=system)。
func (*Tx) CreateRevision ¶
CreateRevision 在事务内创建 verified=1 的版本快照(seq = app 内 max+1)。 与部署终态写、审计同事务组合(fail-closed)。
func (*Tx) EnterPhase ¶
func (t *Tx) EnterPhase(ctx context.Context, id string, from, to DeploymentStatus, extra DeploymentPatch, events ...Event) error
EnterPhase 是事务内的转换写点原语(语义见 Store.EnterPhase)。
func (*Tx) GetAppDerivedState ¶
GetAppDerivedState 是事务内读派生状态(事件翻转与 CAS 同事务的组合点)。
func (*Tx) GetAppDriftConverge ¶
GetAppDriftConverge 是事务内读 opt-in 位(与清位写同事务的组合点)。
func (*Tx) GetAppVolume ¶
GetAppVolume 是事务内取单卷(写后回读)。
func (*Tx) GetPlacement ¶
GetPlacement 是事务内取绑定(供 CAS 前置读取)。
func (*Tx) MarkAppDeleted ¶
MarkAppDeleted 是事务内 tombstone 第二拍(H10/MG-3:与终局事件/审计 同事务组合的形态——引擎 deleting 回收 duty 在受管服务全部移除后原子 落终态,进程在「迁移已落、事件未发」之间崩溃的披露缺口不存在)。
func (*Tx) MarkAppDeleting ¶
MarkAppDeleting 是事务内 tombstone 第一拍(供与审计/事件同事务组合—— T2.17 API 删除走 fail-closed 审计)。
func (*Tx) RegisterAppVolume ¶
RegisterAppVolume 是事务内卷登记(供与事件等同事务组合)。
func (*Tx) ReplaceAppDomains ¶
func (t *Tx) ReplaceAppDomains(ctx context.Context, appID string, declared []DomainServiceRoutes) error
ReplaceAppDomains 是事务内对账域名台账。
func (*Tx) ReusableRevisionByDesiredHash ¶
func (t *Tx) ReusableRevisionByDesiredHash(ctx context.Context, appID, desiredHash string) (Revision, bool, error)
ReusableRevisionByDesiredHash 在事务内裁决成功固化的幂等复用(S18-A6): 按 (app_id, desired_hash) 查既有 active 快照,**且该行同时是该 app 最新 active 快照**时返回复用(seq 不递增、不重复插入);否则返回未命中走插入。
「最新 active」判据兼顾两侧契约:
- 崩溃重放幂等:两事务间崩溃留下的残行必然是最新 active(同 app 互斥 ——残行所属部署未终态,同 app 无更晚成功部署),命中复用,重跑窗口 再固化不产生重复行;
- 回滚/旧态重部署语义:目标 hash 的既有行不是最新(其后已有更新版本) 时不复用——按新 revision 固化,回退版本在「列表即选项」里前移到最新 位(release-semantics §2.4「回滚 = 一次成功部署」)。
superseded 行(保留窗外存档)恒不复用;空哈希(旧形态行)无可比性, 恒走插入。
func (*Tx) SetAppDerivedState ¶
SetAppDerivedStateIfCAS 派生状态翻转(CAS):当前值 ≠ expected 时返回 ErrAppDerivedStateConflict(并发翻转已发生,调用方重读重算、不重发事件)。 与事件写入同事务组合由调用方完成(传入同一 tx)。
func (*Tx) SetAppDriftConverge ¶
SetAppDriftConverge 置位/清除漂移收敛 opt-in(幂等写;审计由调用方与 本写同事务组合——fail-closed)。
func (*Tx) UpdateDeployment ¶
UpdateDeployment 是事务内的行更新原语(S18-A6:成功终态 CAS 与 revision 固化、事件、审计组合在同一 InTx——两事务间崩溃不再留下「revision 已 固化、部署仍 observing」的重放窗口)。语义与 Store 同名方法逐字一致。
func (*Tx) WriteAudit ¶
func (t *Tx) WriteAudit(ctx context.Context, e AuditEntry) error
WriteAudit 在事务内追加审计记录:与同事务内的业务写原子生效或原子 回滚。表级 CHECK(actor/action 非空、result 枚举)使非法审计行直接 产生数据库错误,调用方不得吞掉——这是 fail-closed 的验证路径 (audit_test.go 用真实约束违例证明业务写随之回滚)。
type VersionResolver ¶
type VersionResolver struct {
// contains filtered or unexported fields
}
VersionResolver 是写前直读端口。零状态,直读结果绝不落缓存。
func NewVersionResolver ¶
func NewVersionResolver(d DockerClient) *VersionResolver
NewVersionResolver 构造直读端口。
func (*VersionResolver) CheckVersion ¶
func (r *VersionResolver) CheckVersion(ctx context.Context, kind ObjectKind, id string, expected ObjectVersion) error
CheckVersion 校验调用方持有的令牌是否仍与底座当前版本一致:不一致 (或对象已消失)返回 E_STATE_VERSION_CONFLICT(409)。
func (*VersionResolver) ResolveVersion ¶
func (r *VersionResolver) ResolveVersion(ctx context.Context, kind ObjectKind, id string) (ObjectVersion, error)
ResolveVersion 直读底座对象当前版本作乐观令牌。对象已不存在视为并发 冲突的特例(有人删了它):返回 E_STATE_VERSION_CONFLICT(409,context 标注 reason=object_not_found),不发明清单外错误码。底层传输错误原样 透传(不打契约码)。
type Volume ¶
type Volume struct {
ID string
AppID string
Key string
Name string
Kind VolumeKind
PlatformNodeID string
MountPath string
HostPath string
Status VolumeStatus
CreatedAt time.Time
UpdatedAt time.Time
}
Volume 是卷注册表行投影。Name 即设计表的 docker_name(命名约定值)。
type VolumeKind ¶
type VolumeKind string
VolumeKind 是卷类别词表。
const ( // VolumeKindNamed 命名卷(v0.1 受控子集唯一支持的挂载形态)。 VolumeKindNamed VolumeKind = "named" // VolumeKindBind 宿主绑定挂载(v0.1 校验拒绝;词表先行对齐设计表)。 VolumeKindBind VolumeKind = "bind" )
type VolumeStatus ¶
type VolumeStatus string
VolumeStatus 是卷注册表状态位。
const ( // VolumeActive 在册(被应用声明或已钉节点)。 VolumeActive VolumeStatus = "active" // VolumeOrphaned 应用已删除/解绑,卷保留可发现。 VolumeOrphaned VolumeStatus = "orphaned" // VolumeDiscarded 显式丢弃(admin+confirm+审计)。 VolumeDiscarded VolumeStatus = "discarded" )
type VolumeWrite ¶
type VolumeWrite struct {
AppID string
Key string
Name string
Kind VolumeKind
PlatformNodeID string
MountPath string
HostPath string
}
VolumeWrite 是一次卷登记写入(按 app_id+key 唯一 upsert)。Name 必须 由调用方按命名约定生成(internal/naming.VolumeName)——本层不解释命名。
func (VolumeWrite) Validate ¶
func (w VolumeWrite) Validate() error
Validate 校验 VolumeWrite 词表(kind 必须在册)。