feat: display warning for migration errors

This commit is contained in:
Johannes Loher 2023-07-09 22:19:44 +02:00
parent d555f0fdf4
commit 4ed292f6c0
Signed by: saluu
GPG key ID: 7CB0A9FB553DA045
13 changed files with 126 additions and 49 deletions

View file

@ -289,9 +289,10 @@
"DS4.WarningItemIsNotRollable": "Für das Item '{name}' ({id}) vom Typ '{type}' kann nicht gewürfelt werden.", "DS4.WarningItemIsNotRollable": "Für das Item '{name}' ({id}) vom Typ '{type}' kann nicht gewürfelt werden.",
"DS4.WarningMacrosCanOnlyBeCreatedForOwnedItems": "Makros können nur für besessene Items angelegt werden.", "DS4.WarningMacrosCanOnlyBeCreatedForOwnedItems": "Makros können nur für besessene Items angelegt werden.",
"DS4.WarningInvalidCheckDropped": "Eine ungültige Probe wurde auf die Hotbar gezogen.", "DS4.WarningInvalidCheckDropped": "Eine ungültige Probe wurde auf die Hotbar gezogen.",
"DS4.WarningSystemUpdateCompletedWithErrors": "Aktualisierung des DS4 Systems von Migrationsversion {currentVersion} auf {targetVersion} abgeschlossen, aber es sind Fehler aufgetreten. Bitte prüfen Sie in der Entwicklerkonsole, ob es sich um relevante Fehler handelt, oder ob sie ignoriert werden können. Insbesondere kann https://github.com/foundryvtt/foundryvtt/issues/9672 zu Fehlern führen, die ignoriert werden können.",
"DS4.InfoManuallyEnterSpellModifier": "Der korrekte Wert für den Zauberbonus '{spellModifier}' des Zaubers '{name}' muss manuell angegeben werden.", "DS4.InfoManuallyEnterSpellModifier": "Der korrekte Wert für den Zauberbonus '{spellModifier}' des Zaubers '{name}' muss manuell angegeben werden.",
"DS4.InfoSystemUpdateStart": "Aktualisiere DS4 System von Migrationsversion {currentVersion} auf {targetVersion}. Bitte haben Sie etwas Geduld, schließen Sie nicht das Spiel und fahren Sie nicht den Server herunter.", "DS4.InfoSystemUpdateStart": "Aktualisiere DS4 System von Migrationsversion {currentVersion} auf {targetVersion}. Bitte haben Sie etwas Geduld, schließen Sie nicht das Spiel und fahren Sie nicht den Server herunter.",
"DS4.InfoSystemUpdateCompleted": "Aktualisierung des DS4 Systems von Migrationsversion {currentVersion} auf {targetVersion} erfolgreich!", "DS4.InfoSystemUpdateCompletedSuccessfully": "Aktualisierung des DS4 Systems von Migrationsversion {currentVersion} auf {targetVersion} erfolgreich!",
"DS4.InfoCompendiumMigrationStart": "Aktualisiere Kompendium '{pack}' für DS4 von Migrationsversion {currentVersion} auf {targetVersion}. Bitte haben Sie etwas Geduld, schließen Sie nicht das Spiel und fahren Sie nicht den Server herunter.", "DS4.InfoCompendiumMigrationStart": "Aktualisiere Kompendium '{pack}' für DS4 von Migrationsversion {currentVersion} auf {targetVersion}. Bitte haben Sie etwas Geduld, schließen Sie nicht das Spiel und fahren Sie nicht den Server herunter.",
"DS4.InfoCompendiumMigrationCompleted": "Aktualisierung des Kompendiums '{pack}' für DS4 von Migrationsversion {currentVersion} auf {targetVersion} erfolgreich!", "DS4.InfoCompendiumMigrationCompleted": "Aktualisierung des Kompendiums '{pack}' für DS4 von Migrationsversion {currentVersion} auf {targetVersion} erfolgreich!",
"DS4.UnitRounds": "Runden", "DS4.UnitRounds": "Runden",

View file

@ -289,9 +289,10 @@
"DS4.WarningItemIsNotRollable": "Item '{name}' ({id}) of type '{type}' is not rollable.", "DS4.WarningItemIsNotRollable": "Item '{name}' ({id}) of type '{type}' is not rollable.",
"DS4.WarningMacrosCanOnlyBeCreatedForOwnedItems": "Macros can only be created for owned items.", "DS4.WarningMacrosCanOnlyBeCreatedForOwnedItems": "Macros can only be created for owned items.",
"DS4.WarningInvalidCheckDropped": "An invalid check was dropped on the Hotbar.", "DS4.WarningInvalidCheckDropped": "An invalid check was dropped on the Hotbar.",
"DS4.WarningSystemUpdateCompletedWithErrors": "Migration of DS4 system from migration version {currentVersion} to {targetVersion} completed with errors. Please check the development console (F12) to see whether the errors have significant impact or can be ignored. In particular, https://github.com/foundryvtt/foundryvtt/issues/9672 may cause issues that simply can be ignored.",
"DS4.InfoManuallyEnterSpellModifier": "The correct value of the spell modifier '{spellModifier}' of the spell '{name}' needs to be entered by manually.", "DS4.InfoManuallyEnterSpellModifier": "The correct value of the spell modifier '{spellModifier}' of the spell '{name}' needs to be entered by manually.",
"DS4.InfoSystemUpdateStart": "Migrating DS4 system from migration version {currentVersion} to {targetVersion}. Please be patient and do not close your game or shut down your server.", "DS4.InfoSystemUpdateStart": "Migrating DS4 system from migration version {currentVersion} to {targetVersion}. Please be patient and do not close your game or shut down your server.",
"DS4.InfoSystemUpdateCompleted": "Migration of DS4 system from migration version {currentVersion} to {targetVersion} successful!", "DS4.InfoSystemUpdateCompletedSuccessfully": "Migration of DS4 system from migration version {currentVersion} to {targetVersion} successful!",
"DS4.InfoCompendiumMigrationStart": "Migrating compendium '{pack}' for DS4 from migration version {currentVersion} to {targetVersion}. Please be patient and do not close your game or shut down your server.", "DS4.InfoCompendiumMigrationStart": "Migrating compendium '{pack}' for DS4 from migration version {currentVersion} to {targetVersion}. Please be patient and do not close your game or shut down your server.",
"DS4.InfoCompendiumMigrationCompleted": "Migration of compendium '{pack}' for DS4 from migration version {currentVersion} to {targetVersion} successful!", "DS4.InfoCompendiumMigrationCompleted": "Migration of compendium '{pack}' for DS4 from migration version {currentVersion} to {targetVersion} successful!",
"DS4.UnitRounds": "Rounds", "DS4.UnitRounds": "Rounds",

View file

@ -6,9 +6,10 @@ import { getSceneMigrator, migrateCollection, migrateCompendiums, getCompendiumM
/** @type {import("./migration.js").Migration["migrate"]} */ /** @type {import("./migration.js").Migration["migrate"]} */
async function migrate() { async function migrate() {
await migrateCollection(game.actors, migrateActor); const actorsResult = await migrateCollection(game.actors, migrateActor);
await migrateCollection(game.scenes, migrateScene); const scenesResult = await migrateCollection(game.scenes, migrateScene);
await migrateCompendiums(migrateCompendium); const compendiumsResult = await migrateCompendiums(migrateCompendium);
return actorsResult === "error" || scenesResult === "error" || compendiumsResult === "error" ? "error" : "success";
} }
/** @type {import('./migrationHelpers.js').Migrator<Actor>} */ /** @type {import('./migrationHelpers.js').Migrator<Actor>} */

View file

@ -12,10 +12,16 @@ import {
/** @type {import("./migration.js").Migration["migrate"]} */ /** @type {import("./migration.js").Migration["migrate"]} */
async function migrate() { async function migrate() {
await migrateCollection(game.items, migrateItem); const itemsResult = await migrateCollection(game.items, migrateItem);
await migrateCollection(game.actors, migrateActor); const actorsResult = await migrateCollection(game.actors, migrateActor);
await migrateCollection(game.scenes, migrateScene); const scenesResult = await migrateCollection(game.scenes, migrateScene);
await migrateCompendiums(migrateCompendium); const compendiumsResult = await migrateCompendiums(migrateCompendium);
return itemsResult === "error" ||
actorsResult === "error" ||
scenesResult === "error" ||
compendiumsResult === "error"
? "error"
: "success";
} }
/** @type {import('./migrationHelpers.js').Migrator<Item>} */ /** @type {import('./migrationHelpers.js').Migrator<Item>} */

View file

@ -12,10 +12,16 @@ import {
/** @type {import("./migration.js").Migration["migrate"]} */ /** @type {import("./migration.js").Migration["migrate"]} */
async function migrate() { async function migrate() {
await migrateCollection(game.items, migrateItem); const itemsResult = await migrateCollection(game.items, migrateItem);
await migrateCollection(game.actors, migrateActor); const actorsResult = await migrateCollection(game.actors, migrateActor);
await migrateCollection(game.scenes, migrateScene); const scenesResult = await migrateCollection(game.scenes, migrateScene);
await migrateCompendiums(migrateCompendium); const compendiumsResult = await migrateCompendiums(migrateCompendium);
return itemsResult === "error" ||
actorsResult === "error" ||
scenesResult === "error" ||
compendiumsResult === "error"
? "error"
: "success";
} }
/** @type {import("./migrationHelpers.js").Migrator<Item>} */ /** @type {import("./migrationHelpers.js").Migrator<Item>} */

View file

@ -12,10 +12,16 @@ import {
/** @type {import("./migration.js").Migration["migrate"]} */ /** @type {import("./migration.js").Migration["migrate"]} */
async function migrate() { async function migrate() {
await migrateCollection(game.items, migrateItem); const itemsResult = await migrateCollection(game.items, migrateItem);
await migrateCollection(game.actors, migrateActor); const actorsResult = await migrateCollection(game.actors, migrateActor);
await migrateCollection(game.scenes, migrateScene); const scenesResult = await migrateCollection(game.scenes, migrateScene);
await migrateCompendiums(migrateCompendium); const compendiumsResult = await migrateCompendiums(migrateCompendium);
return itemsResult === "error" ||
actorsResult === "error" ||
scenesResult === "error" ||
compendiumsResult === "error"
? "error"
: "success";
} }
/** @type {import('./migrationHelpers.js').Migrator<Item>} */ /** @type {import('./migrationHelpers.js').Migrator<Item>} */

View file

@ -21,10 +21,16 @@ const secondsPerDay = secondsPerMinute * minutesPerHour * hoursPerDay;
/** @type {import("./migration.js").Migration["migrate"]} */ /** @type {import("./migration.js").Migration["migrate"]} */
async function migrate() { async function migrate() {
await migrateCollection(game.items, migrateItem); const itemsResult = await migrateCollection(game.items, migrateItem);
await migrateCollection(game.actors, migrateActor); const actorsResult = await migrateCollection(game.actors, migrateActor);
await migrateCollection(game.scenes, migrateScene); const scenesResult = await migrateCollection(game.scenes, migrateScene);
await migrateCompendiums(migrateCompendium); const compendiumsResult = await migrateCompendiums(migrateCompendium);
return itemsResult === "error" ||
actorsResult === "error" ||
scenesResult === "error" ||
compendiumsResult === "error"
? "error"
: "success";
} }
/** @type {import('./migrationHelpers.js').Migrator<Item>} */ /** @type {import('./migrationHelpers.js').Migrator<Item>} */

View file

@ -12,10 +12,16 @@ import {
/** @type {import("./migration.js").Migration["migrate"]} */ /** @type {import("./migration.js").Migration["migrate"]} */
async function migrate() { async function migrate() {
await migrateCollection(game.items, migrateItem); const itemsResult = await migrateCollection(game.items, migrateItem);
await migrateCollection(game.actors, migrateActor); const actorsResult = await migrateCollection(game.actors, migrateActor);
await migrateCollection(game.scenes, migrateScene); const scenesResult = await migrateCollection(game.scenes, migrateScene);
await migrateCompendiums(migrateCompendium); const compendiumsResult = await migrateCompendiums(migrateCompendium);
return itemsResult === "error" ||
actorsResult === "error" ||
scenesResult === "error" ||
compendiumsResult === "error"
? "error"
: "success";
} }
/** @type {import('./migrationHelpers.js').Migrator<Item>} */ /** @type {import('./migrationHelpers.js').Migrator<Item>} */

View file

@ -12,10 +12,16 @@ import {
/** @type {import("./migration.js").Migration["migrate"]} */ /** @type {import("./migration.js").Migration["migrate"]} */
async function migrate() { async function migrate() {
await migrateCollection(game.items, migrateItem); const itemsResult = await migrateCollection(game.items, migrateItem);
await migrateCollection(game.actors, migrateActor); const actorsResult = await migrateCollection(game.actors, migrateActor);
await migrateCollection(game.scenes, migrateScene); const scenesResult = await migrateCollection(game.scenes, migrateScene);
await migrateCompendiums(migrateCompendium); const compendiumsResult = await migrateCompendiums(migrateCompendium);
return itemsResult === "error" ||
actorsResult === "error" ||
scenesResult === "error" ||
compendiumsResult === "error"
? "error"
: "success";
} }
/** @type {import('./migrationHelpers.js').Migrator<Item>} */ /** @type {import('./migrationHelpers.js').Migrator<Item>} */

View file

@ -13,10 +13,16 @@ import {
/** @type {import("./migration.js").Migration["migrate"]} */ /** @type {import("./migration.js").Migration["migrate"]} */
async function migrate() { async function migrate() {
await migrateCollection(game.items, migrateItem); const itemsResult = await migrateCollection(game.items, migrateItem);
await migrateCollection(game.actors, migrateActor); const actorsResult = await migrateCollection(game.actors, migrateActor);
await migrateCollection(game.scenes, migrateScene); const scenesResult = await migrateCollection(game.scenes, migrateScene);
await migrateCompendiums(migrateCompendium); const compendiumsResult = await migrateCompendiums(migrateCompendium);
return itemsResult === "error" ||
actorsResult === "error" ||
scenesResult === "error" ||
compendiumsResult === "error"
? "error"
: "success";
} }
/** @type {import('./migrationHelpers.js').Migrator<ActiveEffect>} */ /** @type {import('./migrationHelpers.js').Migrator<ActiveEffect>} */

View file

@ -12,9 +12,10 @@ import {
/** @type {import("./migration.js").Migration["migrate"]} */ /** @type {import("./migration.js").Migration["migrate"]} */
async function migrate() { async function migrate() {
await migrateCollection(game.actors, migrateActor); const actorsResult = await migrateCollection(game.actors, migrateActor);
await migrateCollection(game.scenes, migrateScene); const scenesResult = await migrateCollection(game.scenes, migrateScene);
await migrateCompendiums(migrateCompendium); const compendiumsResult = await migrateCompendiums(migrateCompendium);
return actorsResult === "error" || scenesResult === "error" || compendiumsResult === "error" ? "error" : "success";
} }
const itemIdRegex = /Item\.([a-zA-Z0-9]+)/; const itemIdRegex = /Item\.([a-zA-Z0-9]+)/;

View file

@ -58,12 +58,17 @@ async function migrateFromTo(oldMigrationVersion, targetMigrationVersion) {
{ permanent: true }, { permanent: true },
); );
/** @type {Result} */
let result = "success";
for (const [i, { migrate }] of migrationsToExecute.entries()) { for (const [i, { migrate }] of migrationsToExecute.entries()) {
const currentMigrationVersion = oldMigrationVersion + i + 1; const currentMigrationVersion = oldMigrationVersion + i + 1;
logger.info("executing migration script", currentMigrationVersion); logger.info("executing migration script", currentMigrationVersion);
try { try {
await migrate(); const r = await migrate();
getGame().settings.set("ds4", "systemMigrationVersion", currentMigrationVersion); getGame().settings.set("ds4", "systemMigrationVersion", currentMigrationVersion);
if (r === "error") {
result = "error";
}
} catch (err) { } catch (err) {
notifications.error( notifications.error(
getGame().i18n.format("DS4.ErrorDuringMigration", { getGame().i18n.format("DS4.ErrorDuringMigration", {
@ -78,13 +83,23 @@ async function migrateFromTo(oldMigrationVersion, targetMigrationVersion) {
} }
} }
if (result === "success") {
notifications.info( notifications.info(
getGame().i18n.format("DS4.InfoSystemUpdateCompleted", { getGame().i18n.format("DS4.InfoSystemUpdateCompletedSuccessfully", {
currentVersion: oldMigrationVersion, currentVersion: oldMigrationVersion,
targetVersion: targetMigrationVersion, targetVersion: targetMigrationVersion,
}), }),
{ permanent: true }, { permanent: true },
); );
} else {
notifications.warn(
getGame().i18n.format("DS4.WarningSystemUpdateCompletedWithErrors", {
currentVersion: oldMigrationVersion,
targetVersion: targetMigrationVersion,
}),
{ permanent: true },
);
}
} }
} }
@ -159,9 +174,11 @@ function getTargetMigrationVersion() {
return migrations.length; return migrations.length;
} }
/** @typedef {"success" | "error"} Result */
/** /**
* @typedef {object} Migration * @typedef {object} Migration
* @property {() => Promise<void>} migrate * @property {() => Promise<Result>} migrate
* @property {import("./migrationHelpers").CompendiumMigrator} migrateCompendium * @property {import("./migrationHelpers").CompendiumMigrator} migrateCompendium
*/ */

View file

@ -17,9 +17,11 @@ import { getGame } from "../utils/utils.js";
* @template T * @template T
* @param {WorldCollection} collection * @param {WorldCollection} collection
* @param {Migrator<T>} migrateDocument * @param {Migrator<T>} migrateDocument
* @returns {Promise<void>} A promise that resolves once the migration is complete * @returns {Promise<import("./migration.js").Result>} A promise that resolves once the migration is complete
*/ */
export async function migrateCollection(collection, migrateDocument) { export async function migrateCollection(collection, migrateDocument) {
/** @type {import("./migration.js").Result} */
let result = "success";
const { documentName } = collection.constructor; const { documentName } = collection.constructor;
for (const document of collection) { for (const document of collection) {
logger.info(`Migrating ${documentName} document ${document.name} (${document.id})`); logger.info(`Migrating ${documentName} document ${document.name} (${document.id})`);
@ -30,8 +32,10 @@ export async function migrateCollection(collection, migrateDocument) {
`Error during migration of ${documentName} document ${document.name} (${document.id}), continuing anyways.`, `Error during migration of ${documentName} document ${document.name} (${document.id}), continuing anyways.`,
err, err,
); );
result = "error";
} }
} }
return result;
} }
/** /**
@ -93,20 +97,26 @@ export function getSceneMigrator(migrateActor) {
}; };
} }
/** @typedef {(pack: CompendiumCollection) => Promise<void>} CompendiumMigrator */ /** @typedef {(pack: CompendiumCollection) => Promise<import("./migration.js").Result>} CompendiumMigrator */
/** /**
* Migrate world compendium packs. * Migrate world compendium packs.
* @param {CompendiumMigrator} migrateCompendium A function for migrating a single compendium pack * @param {CompendiumMigrator} migrateCompendium A function for migrating a single compendium pack
* @returns {Promise<void>} A promise that resolves once the migration is complete * @returns {Promise<import("./migration.js").Result>} A promise that resolves once the migration is complete
*/ */
export async function migrateCompendiums(migrateCompendium) { export async function migrateCompendiums(migrateCompendium) {
/** @type {import("./migration.js").Result} */
let result = "success";
for (const compendium of getGame().packs ?? []) { for (const compendium of getGame().packs ?? []) {
if (compendium.metadata.package !== "world") continue; if (compendium.metadata.package !== "world") continue;
if (!["Actor", "Item", "Scene"].includes(compendium.metadata.type)) continue; if (!["Actor", "Item", "Scene"].includes(compendium.metadata.type)) continue;
await migrateCompendium(compendium); const r = await migrateCompendium(compendium);
if (r === "error") {
result = "error";
} }
} }
return result;
}
/** /**
* @typedef {object} Migrators * @typedef {object} Migrators
@ -126,6 +136,8 @@ export function getCompendiumMigrator(
{ migrateToTemplateEarly = true } = {}, { migrateToTemplateEarly = true } = {},
) { ) {
return async (pack) => { return async (pack) => {
/** @type {import("./migration.js").Result} */
let result = "success";
const type = pack.metadata.type; const type = pack.metadata.type;
if (!["Actor", "Item", "Scene"].includes(type)) return; if (!["Actor", "Item", "Scene"].includes(type)) return;
const wasLocked = pack.locked; const wasLocked = pack.locked;
@ -151,6 +163,7 @@ export function getCompendiumMigrator(
`Error during migration of document ${doc.name} (${doc.id}) in compendium ${pack.collection}, continuing anyways.`, `Error during migration of document ${doc.name} (${doc.id}) in compendium ${pack.collection}, continuing anyways.`,
err, err,
); );
result = "error";
} }
} }
@ -158,5 +171,6 @@ export function getCompendiumMigrator(
await pack.migrate(); await pack.migrate();
} }
await pack.configure({ locked: wasLocked }); await pack.configure({ locked: wasLocked });
return result;
}; };
} }