From 1fad8db453feba18f8b3bf501506450ea729e95f Mon Sep 17 00:00:00 2001 From: xuans Date: Thu, 1 Oct 2026 13:05:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E7=BD=B2=E9=94=81?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=A4=B1=E8=B4=A5=E4=BA=8B=E5=8A=A1=E7=BB=88?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 锁获取、锁归属写入或锁阶段持久化失败时,主动释放已取得的锁并写入 rolled_back 或 recovery_required,避免部署事务永久停留在 pending。 --- backend/internal/deployment/service.go | 42 +++++++++++++++++--------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/backend/internal/deployment/service.go b/backend/internal/deployment/service.go index 6b9d6c1..445c67b 100644 --- a/backend/internal/deployment/service.go +++ b/backend/internal/deployment/service.go @@ -239,21 +239,6 @@ func (s *Service) deployOne(ctx context.Context, server Server, artifact Artifac releaseLocks() } }() - for _, lockPath := range lockPaths { - if err := client.Lock(ctx, lockPath); err != nil { - result.FailureCode = FailureLock - result.Message = fmt.Sprintf("无法取得部署锁 %s,可能存在并发部署或遗留锁;未修改当前证书,请人工核查:%v", lockPath, err) - return result - } - heldLocks = append(heldLocks, lockPath) - if transactionEnabled { - if err := client.(EvidenceClient).CreateOwnedLock(ctx, lockPath, journalRecord.Evidence.LockToken); err != nil { - result.FailureCode = FailureUnavailable - result.Message = fmt.Sprintf("保存部署锁归属失败:%v", err) - return result - } - } - } persistTransaction := func(persistContext context.Context, phase string) error { if !transactionEnabled { return nil @@ -272,9 +257,36 @@ func (s *Service) deployOne(ctx context.Context, server Server, artifact Artifac result.Message += fmt.Sprintf(";保存部署事务最终状态失败:%v", err) } } + finalizeLockAcquisitionFailure := func() { + releaseLocks() + status := TransactionStatusRolledBack + if len(heldLocks) > 0 || result.FailureCode == FailureLockRelease { + retainLocks = true + status = TransactionStatusRecoveryRequired + } + finishTransaction(status, result.Message) + } + for _, lockPath := range lockPaths { + if err := client.Lock(ctx, lockPath); err != nil { + result.FailureCode = FailureLock + result.Message = fmt.Sprintf("无法取得部署锁 %s,可能存在并发部署或遗留锁;未修改当前证书,请人工核查:%v", lockPath, err) + finalizeLockAcquisitionFailure() + return result + } + heldLocks = append(heldLocks, lockPath) + if transactionEnabled { + if err := client.(EvidenceClient).CreateOwnedLock(ctx, lockPath, journalRecord.Evidence.LockToken); err != nil { + result.FailureCode = FailureUnavailable + result.Message = fmt.Sprintf("保存部署锁归属失败:%v", err) + finalizeLockAcquisitionFailure() + return result + } + } + } if err := persistTransaction(ctx, TransactionPhaseLocked); err != nil { result.FailureCode = FailureUnavailable result.Message = fmt.Sprintf("保存部署锁阶段失败:%v", err) + finalizeLockAcquisitionFailure() return result } backups := make([]backupFile, 0, len(paths))