Scert/backend/internal/deployment/transaction.go
xuans 0e48dc9231 开发检查点:完成可信恢复证据与部署回归
补充部署事务恢复证据、锁归属和文件摘要校验,接入站点恢复基线,更新三数据库迁移与回归测试。
2026-10-01 11:27:23 +08:00

90 lines
3.0 KiB
Go

package deployment
import (
"context"
"strings"
"time"
)
// TransactionBackup 描述一次部署事务保存的旧文件。
type TransactionBackup struct {
Original string `json:"original"`
Saved string `json:"saved"`
OriginalExists bool `json:"original_exists"`
OriginalDigest string `json:"original_digest,omitempty"`
}
// TransactionRecord 保存远程部署事务的可恢复现场,不包含证书内容或凭据。
type TransactionRecord struct {
ID string
TaskID string
AttemptID string
AttemptNumber int
ResultIndex int
ServerID string
ServerName string
Paths []string
TemporaryPaths []string
InstalledPaths []string
Backups []TransactionBackup
LockPaths []string
ReloadAttempted bool
Phase string
Status string
Message string
UpdatedAt time.Time
Evidence *RecoveryEvidence
}
// TransactionJournal 持久化部署现场,保证进程重启后仍能识别未提交事务。
type TransactionJournal interface {
CreateDeploymentTransaction(context.Context, TransactionRecord) error
UpdateDeploymentTransaction(context.Context, TransactionRecord) error
FinishDeploymentTransaction(context.Context, string, string, string) error
ListPendingDeploymentTransactions(context.Context) ([]TransactionRecord, error)
}
const (
TransactionStatusPending = "pending"
TransactionStatusCommitted = "committed"
TransactionStatusRolledBack = "rolled_back"
TransactionStatusRecoveryRequired = "recovery_required"
TransactionPhaseLocked = "locked"
TransactionPhaseAcquiring = "acquiring"
TransactionPhaseRollbackVerified = "rollback_verified"
TransactionPhaseCommitVerified = "commit_verified"
TransactionPhaseCommitting = "committing"
TransactionPhaseUploaded = "uploaded"
TransactionPhaseReplacing = "replacing"
TransactionPhaseInstalled = "installed"
TransactionPhaseReloadAttempted = "reload_attempted"
TransactionPhaseCommitted = "committed"
TransactionPhaseRolledBack = "rolled_back"
)
type transactionContextKey struct{}
// TransactionContext 保存任务与尝试标识,供部署层建立可追溯事务记录。
type TransactionContext struct {
TaskID string
AttemptID string
AttemptNumber int
}
// WithTransactionContext 将任务尝试标识绑定到证书部署上下文。
func WithTransactionContext(ctx context.Context, value TransactionContext) context.Context {
value.TaskID = strings.TrimSpace(value.TaskID)
value.AttemptID = strings.TrimSpace(value.AttemptID)
return context.WithValue(ctx, transactionContextKey{}, value)
}
// TransactionContextFromContext 读取任务尝试标识。
func TransactionContextFromContext(ctx context.Context) (TransactionContext, bool) {
value, ok := ctx.Value(transactionContextKey{}).(TransactionContext)
if !ok || strings.TrimSpace(value.TaskID) == "" || strings.TrimSpace(value.AttemptID) == "" {
return TransactionContext{}, false
}
return value, true
}