librestore-<scope>-<时间戳.微秒> 带 ".",冻结协调器的 job 白名单只收 [A-Za-z0-9_-],所以每次恢复都在开窗口时被拒(invalid freeze request), 作业随后被接管扫成失败。改纳秒整数,并加测试锁住该约束。 试过:make verify 15 项全绿;真实恢复复现该错误后修复。
This commit is contained in:
@@ -36,8 +36,13 @@
|
||||
目标实例之后取图/附件会指向测试环境的桶,或直接取不到。现在写入前把定位符里的桶
|
||||
换成本次目标桶(键不变),解析不出来就报错而不是写一行指向别处的资源。
|
||||
|
||||
- **恢复作业 id 让维护窗口拒绝**:`librestore-<scope>-<时间戳.微秒>` 带 `.`,而冻结协调器
|
||||
只接受 `[A-Za-z0-9_-]`,每次恢复都在开窗口时被拒(`invalid freeze request`),作业随后被
|
||||
接管扫成失败。改用纳秒整数,并加测试锁住"id 必须是维护窗口可接受的标识"。
|
||||
|
||||
### Tests
|
||||
|
||||
- `internal/httpapi/library_restore_test.go`:恢复作业 id 必须能被维护窗口接受。
|
||||
- `internal/releaseadapter/v071/resource_locator_test.go`:嵌套/单层两种定位符换桶、裸键原样、
|
||||
非法形状拒绝。
|
||||
- `internal/releaseadapter/v071/search_empty_index_test.go`:空索引=空基线、有文档无范围字段必须报错。
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -86,7 +87,10 @@ func libraryRestoreEnqueue(w http.ResponseWriter, r *http.Request, config Config
|
||||
return
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
jobID := "librestore-" + request.Scope + "-" + now.Format("20060102T150405.000000")
|
||||
// 作业 id 会作为维护窗口的 job 标识落进 freeze journal,而冻结协调器只接受
|
||||
// [A-Za-z0-9_-]:带 "." 的时间戳会让恢复在开窗口时被拒(真跑报 invalid freeze request),
|
||||
// 所以用纳秒整数,和同步作业保持一致。
|
||||
jobID := "librestore-" + request.Scope + "-" + strconv.FormatInt(now.UnixNano(), 10)
|
||||
job, reused, err := store.CreateLibraryJob(r.Context(), governance.LibraryJob{
|
||||
ID: jobID, Scope: request.Scope, Kind: governance.LibraryJobRestore,
|
||||
IdempotencyKey: "library.restore:" + request.Scope + ":" + request.SnapshotID,
|
||||
@@ -107,7 +111,7 @@ func libraryRestoreEnqueue(w http.ResponseWriter, r *http.Request, config Config
|
||||
if reused && (job.State == governance.LibraryJobFailed || job.State == governance.LibraryJobCancelled) {
|
||||
job, reused, err = store.CreateLibraryJob(r.Context(), governance.LibraryJob{
|
||||
ID: jobID + "-retry", Scope: request.Scope, Kind: governance.LibraryJobRestore,
|
||||
IdempotencyKey: "library.restore:" + request.Scope + ":" + request.SnapshotID + ":retry:" + now.Format("20060102T150405.000000000"),
|
||||
IdempotencyKey: "library.restore:" + request.Scope + ":" + request.SnapshotID + ":retry:" + strconv.FormatInt(now.UnixNano(), 10),
|
||||
RequestDigest: digest, TargetSnapshotID: request.SnapshotID, Actor: identity.Username,
|
||||
}, governance.SyncStages(), now)
|
||||
if err != nil || reused {
|
||||
|
||||
@@ -85,3 +85,31 @@ func TestLibraryJobResumeRejectsNonFailedJobs(t *testing.T) {
|
||||
t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复作业 id 会作为维护窗口的 job 标识落进 freeze journal,协调器只接受
|
||||
// [A-Za-z0-9_-]。带 "." 的时间戳曾经让每次恢复都在开窗口时被拒(invalid freeze request)。
|
||||
func TestLibraryRestoreJobIDIsAFreezeSafeIdentifier(t *testing.T) {
|
||||
store := &fakeLibraryStore{fakeJobStore: fakeJobStore{enqueueEchoRequestedID: true}}
|
||||
digest, err := libraryRestoreParamsDigest("internal", "snap-1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
store.grant = &governance.LibraryReleaseAuthorization{ID: "a", Scope: "internal", SnapshotID: "snap-1",
|
||||
ParamsDigest: digest, ExpiresAt: now.Add(time.Hour), CreatedAt: now}
|
||||
config := Config{Store: store, ProductionReleaseRequestsEnabled: true, ProductionBackupRestoreVerified: true}
|
||||
recorder := httptest.NewRecorder()
|
||||
libraryRestoreEnqueue(recorder, restoreRequest(`{"scope":"internal","snapshot_id":"snap-1"}`, roleAdmin), config)
|
||||
if recorder.Code != http.StatusAccepted {
|
||||
t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String())
|
||||
}
|
||||
id := store.lastJob.ID
|
||||
if id == "" || len(id) > 128 {
|
||||
t.Fatalf("作业 id 形状不对:%q", id)
|
||||
}
|
||||
for _, r := range id {
|
||||
if !(r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r >= '0' && r <= '9' || r == '-' || r == '_') {
|
||||
t.Fatalf("作业 id 含维护窗口不接受的字符 %q:%q", r, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user