Skip to content

Commit b4c4d3f

Browse files
committed
Retain completed migration results when later store discovery fails
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
1 parent 45f522e commit b4c4d3f

1 file changed

Lines changed: 31 additions & 26 deletions

File tree

‎loopx/control_plane/coordination/authority_format_upgrade.ts‎

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -66,36 +66,41 @@ async function upgradeSqlite(directory: string, goal: string, execute: boolean):
6666
* All stores, including unselected shadows, must be readable by the new binary. */
6767
export async function upgradeAuthorityFormats(roots: readonly string[], execute: boolean): Promise<JsonObject> {
6868
const results: JsonObject[] = [];
69-
for (const root of [...new Set(roots.map(requireLocalAuthorityRuntimeRoot))]) {
70-
for (const provider of ["file", "sqlite"] as const) {
71-
const directory = join(root, "authority", `${provider}-v0`);
72-
const names = (await entries(directory)).filter(name =>
73-
(provider === "file" ? /^authority-store-[0-9a-f]{16}\.json$/ : /^authority-[0-9a-f]{64}\.sqlite$/).test(name));
74-
if (provider === "file") names.push(...(await entries(join(directory, "rollback")))
75-
.filter(name => /^authority-store-[0-9a-f]{24}\.json$/.test(name)).map(name => join("rollback", name)));
76-
for (const name of names.sort()) {
77-
const path = join(directory, name);
78-
let goal: string | null = null;
79-
try {
80-
const detected = await inspectAuthorityFormat(path);
81-
if (detected.artifact_kind !== "authority_store" || detected.provider !== provider) {
82-
throw new Error("Detected format does not match this provider directory; no migration selected");
69+
try {
70+
for (const root of [...new Set(roots.map(requireLocalAuthorityRuntimeRoot))]) {
71+
for (const provider of ["file", "sqlite"] as const) {
72+
const directory = join(root, "authority", `${provider}-v0`);
73+
const names = (await entries(directory)).filter(name =>
74+
(provider === "file" ? /^authority-store-[0-9a-f]{16}\.json$/ : /^authority-[0-9a-f]{64}\.sqlite$/).test(name));
75+
if (provider === "file") names.push(...(await entries(join(directory, "rollback")))
76+
.filter(name => /^authority-store-[0-9a-f]{24}\.json$/.test(name)).map(name => join("rollback", name)));
77+
for (const name of names.sort()) {
78+
const path = join(directory, name);
79+
let goal: string | null = null;
80+
try {
81+
const detected = await inspectAuthorityFormat(path);
82+
if (detected.artifact_kind !== "authority_store" || detected.provider !== provider) {
83+
throw new Error("Detected format does not match this provider directory; no migration selected");
84+
}
85+
goal = detected.goal_id;
86+
const expected = provider === "file" ? new FileAuthorityStore(directory, goal, {existingOnly: true}).path
87+
: sqliteAuthorityPath(directory, goal);
88+
if (!name.startsWith("rollback") && expected !== path) throw new Error("Authority filename does not match its goal");
89+
const result = provider === "file" ? await migrateFileAuthorityStore(directory, goal, execute, {}, name.startsWith("rollback") ? path : undefined)
90+
: await upgradeSqlite(directory, goal, execute);
91+
results.push({goal_id: goal, detected_format: detected.format, ...result});
92+
} catch (error) {
93+
// Earlier stores may already have migrated. Never report global rollback
94+
// or overwrite their later commits. Retry resumes per-store publication.
95+
return {status: "failed", results, failed_provider: provider, failed_goal_id: goal,
96+
reason: error instanceof Error ? error.message : "Format upgrade failed", retry_safe: true};
8397
}
84-
goal = detected.goal_id;
85-
const expected = provider === "file" ? new FileAuthorityStore(directory, goal, {existingOnly: true}).path
86-
: sqliteAuthorityPath(directory, goal);
87-
if (!name.startsWith("rollback") && expected !== path) throw new Error("Authority filename does not match its goal");
88-
const result = provider === "file" ? await migrateFileAuthorityStore(directory, goal, execute, {}, name.startsWith("rollback") ? path : undefined)
89-
: await upgradeSqlite(directory, goal, execute);
90-
results.push({goal_id: goal, detected_format: detected.format, ...result});
91-
} catch (error) {
92-
// Earlier stores may already have migrated. Never report global rollback
93-
// or overwrite their later commits. Retry resumes per-store publication.
94-
return {status: "failed", results, failed_provider: provider, failed_goal_id: goal,
95-
reason: error instanceof Error ? error.message : "Format upgrade failed", retry_safe: true};
9698
}
9799
}
98100
}
101+
} catch (error) {
102+
return {status: "failed", results, reason: error instanceof Error ? error.message : "Store discovery failed",
103+
retry_safe: true};
99104
}
100105
return {status: execute ? "upgraded" : "planned", results, authority_changed: false};
101106
}

0 commit comments

Comments
 (0)