From 5212375c3464cbc0288436ea8e5f68424d937b47 Mon Sep 17 00:00:00 2001 From: Matchu Date: Mon, 12 Apr 2021 18:58:28 -0700 Subject: [PATCH] Handle very large asset manifests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Huh, so apparently the "MiniMME11-S1: Approaching Eventide Skirt" on the Acara has 1000 layer images lol. This caused the manifest string to overflow the MySQL `TEXT` field, and fail to parse as valid JSON when loading it back for the client. I've updated the database to use `MEDIUMTEXT` instead, and added a warning message & skip behavior when the manifest size would exceed the database limit, and added graceful error handling for the invalid JSON scenario. Now, we don't crash, and the data self-repairs, and keeps in a better state in the first place! But I'm also worried about this asset, it doesn't play correctly anyway, and I'm not sure if that's an overload on our end, or just a flat problem in the JS. (There's no error message on the client, it just… loads all the layers, then shows no play button, seemingly self-satisfied.) --- src/server/types/AppearanceLayer.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/server/types/AppearanceLayer.js b/src/server/types/AppearanceLayer.js index ee4ab29d..94de0669 100644 --- a/src/server/types/AppearanceLayer.js +++ b/src/server/types/AppearanceLayer.js @@ -357,7 +357,16 @@ function convertLayerTypeToSwfAssetType(layerType) { * image for this layer, it could be a supporting sprite for the JS library!) */ async function loadAndCacheAssetDataFromManifest(db, layer) { - let manifest = layer.manifest && JSON.parse(layer.manifest); + let manifest; + try { + manifest = layer.manifest && JSON.parse(layer.manifest); + } catch (e) { + console.error( + `Layer ${layer.id} has invalid manifest JSON: ` + + `${JSON.stringify(layer.manifest)}` + ); + manifest = null; + } // When the manifest is specifically null, that means we don't know if // it exists yet. Load it to find out! @@ -430,6 +439,14 @@ async function loadAndCacheAssetManifest(db, layer) { // reload all the missing ones at that time. const manifestJson = manifest ? JSON.stringify(manifest) : ""; + if (manifestJson.length > 16777215) { + console.warn( + `Skipping saving asset manifest for layer ${layer.id}, because its ` + + `length is ${manifestJson.length}, which exceeds the database limit.` + ); + return manifest; + } + const [ result, ] = await db.execute(