2020-08-17 18:23:39 -07:00
|
|
|
// This is a big bulk script to load the asset manifest from images.neopets.com
|
|
|
|
// for every asset, and save it to the database for fast loading!
|
|
|
|
//
|
|
|
|
// The site works fine without this: when it runs into an asset where we don't
|
|
|
|
// have the manifest cached, it loads it and caches it in real time. But this
|
|
|
|
// is a nice way to warm things up to get started!
|
|
|
|
//
|
|
|
|
// We shouldn't have to run this regularly in general, but we might want to
|
|
|
|
// re-run it once Neopets adds more manifests. Right now, we save an empty
|
|
|
|
// placeholder when no manifest exists, but someday we want to fill it in
|
|
|
|
// instead!
|
2020-08-19 17:19:15 -07:00
|
|
|
const { argv } = require("yargs");
|
2020-08-17 18:23:39 -07:00
|
|
|
const PromisePool = require("es6-promise-pool");
|
|
|
|
|
|
|
|
const connectToDb = require("../src/server/db");
|
2020-12-28 14:00:11 -08:00
|
|
|
const neopetsAssets = require("../src/server/neopets-assets");
|
2020-08-17 18:23:39 -07:00
|
|
|
|
|
|
|
async function cacheAssetManifests(db) {
|
2021-01-21 15:14:23 -08:00
|
|
|
// Normally, we skip manifests that we already have. But you can run with
|
|
|
|
// --resync-existing to check old manifests for changes! (This might take,
|
|
|
|
// like, multiple minutes to even run this first query!)
|
|
|
|
const condition = argv.resyncExisting
|
|
|
|
? `1`
|
|
|
|
: `manifest IS NULL OR manifest = ""`;
|
|
|
|
|
2020-12-28 14:04:28 -08:00
|
|
|
const [rows] = await db.execute(
|
2021-01-20 09:49:05 -08:00
|
|
|
`SELECT id, url, manifest FROM swf_assets ` +
|
2021-01-21 15:14:23 -08:00
|
|
|
`WHERE ${condition} AND id >= ? ` +
|
2020-08-19 17:19:15 -07:00
|
|
|
`ORDER BY id`,
|
|
|
|
[argv.start || 0]
|
2020-08-17 18:23:39 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
const numRowsTotal = rows.length;
|
|
|
|
let numRowsStarted = 0;
|
2021-01-20 09:49:05 -08:00
|
|
|
let numRowsUpdated = 0;
|
2020-08-17 18:23:39 -07:00
|
|
|
let numRowsDone = 0;
|
|
|
|
|
|
|
|
async function cacheAssetManifest(row) {
|
|
|
|
try {
|
2020-12-28 14:00:11 -08:00
|
|
|
let manifest = await neopetsAssets.loadAssetManifest(row.url);
|
2020-08-17 18:23:39 -07:00
|
|
|
|
|
|
|
// After loading, write the new manifest. We make sure to write an empty
|
|
|
|
// string if there was no manifest, to signify that it doesn't exist, so
|
|
|
|
// we don't need to bother looking it up again.
|
|
|
|
//
|
|
|
|
// TODO: Someday the manifests will all exist, right? So we'll want to
|
|
|
|
// reload all the missing ones at that time.
|
|
|
|
manifest = manifest || "";
|
2021-01-20 09:49:05 -08:00
|
|
|
let updated = false;
|
|
|
|
if (row.manifest !== manifest) {
|
|
|
|
if (argv.mode === "dump") {
|
|
|
|
// Make it a JSON string, then escape the string for the query.
|
|
|
|
// Hacky for sure!
|
|
|
|
const escapedManifest = JSON.stringify(JSON.stringify(manifest));
|
|
|
|
console.log(
|
2021-03-11 02:23:40 -08:00
|
|
|
`UPDATE swf_assets SET manifest = ${escapedManifest}, ` +
|
|
|
|
`manifest_cached_at = CURRENT_TIMESTAMP() ` +
|
2021-01-20 09:49:05 -08:00
|
|
|
`WHERE id = ${row.id} LIMIT 1;`
|
2020-08-19 17:19:15 -07:00
|
|
|
);
|
2021-01-20 09:49:05 -08:00
|
|
|
} else {
|
|
|
|
const [
|
|
|
|
result,
|
|
|
|
] = await db.execute(
|
2021-03-11 02:23:40 -08:00
|
|
|
`UPDATE swf_assets SET manifest = ?, ` +
|
|
|
|
`manifest_cached_at = CURRENT_TIMESTAMP() ` +
|
|
|
|
`WHERE id = ? LIMIT 1;`,
|
2021-01-20 09:49:05 -08:00
|
|
|
[manifest, row.id]
|
|
|
|
);
|
|
|
|
if (result.affectedRows !== 1) {
|
|
|
|
throw new Error(
|
|
|
|
`Expected to affect 1 asset, but affected ${result.affectedRows}`
|
|
|
|
);
|
|
|
|
}
|
2020-08-19 17:19:15 -07:00
|
|
|
}
|
2021-01-20 09:49:05 -08:00
|
|
|
updated = true;
|
|
|
|
numRowsUpdated++;
|
2020-08-17 18:23:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
numRowsDone++;
|
|
|
|
|
|
|
|
const percent = Math.floor((numRowsDone / numRowsTotal) * 100);
|
2021-01-21 10:38:47 -08:00
|
|
|
const shouldSkipLogging = argv.skipUnchanged && !updated;
|
|
|
|
if (!shouldSkipLogging) {
|
|
|
|
// write to stderr, to not disrupt the dump
|
|
|
|
console.error(
|
|
|
|
`${percent}% ${numRowsDone}/${numRowsTotal} ` +
|
|
|
|
`(Exists? ${Boolean(manifest)}. Updated? ${updated}. ` +
|
|
|
|
`Layer: ${row.id}, ${row.url}.)`
|
|
|
|
);
|
|
|
|
}
|
2020-08-17 18:23:39 -07:00
|
|
|
} catch (e) {
|
|
|
|
console.error(`Error loading layer ${row.id}, ${row.url}.`, e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function promiseProducer() {
|
|
|
|
if (numRowsStarted < numRowsTotal) {
|
|
|
|
const promise = cacheAssetManifest(rows[numRowsStarted]);
|
|
|
|
numRowsStarted++;
|
|
|
|
return promise;
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const pool = new PromisePool(promiseProducer, 10);
|
|
|
|
await pool.start();
|
|
|
|
|
2020-08-19 17:19:15 -07:00
|
|
|
// write to stderr, to not disrupt the dump
|
2021-01-20 09:49:05 -08:00
|
|
|
console.error(`Done! Updated ${numRowsUpdated} of ${numRowsDone} rows.`);
|
2020-08-17 18:23:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async function main() {
|
|
|
|
const db = await connectToDb();
|
|
|
|
try {
|
|
|
|
await cacheAssetManifests(db);
|
|
|
|
} catch (e) {
|
|
|
|
db.close();
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
db.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
main().catch((e) => {
|
|
|
|
console.error(e);
|
|
|
|
process.exitCode = 1;
|
|
|
|
});
|