|  | 
| 1 | 1 | import { mainLog, mongo, redis } from "../index.js"; | 
|  | 2 | +import pLimit from "p-limit"; | 
|  | 3 | + | 
|  | 4 | +const limit = pLimit(1); | 
| 2 | 5 | 
 | 
| 3 | 6 | export default async function () { | 
| 4 |  | -	const log = mainLog.extend("updateScience"), | 
| 5 |  | -		key = "pmd-api.scienceUpdates"; | 
| 6 |  | - | 
| 7 |  | -	log("Updating..."); | 
| 8 |  | -	const scienceUpdates = await redis.hvals(key); | 
| 9 |  | - | 
| 10 |  | -	let invalidEntries: string[] = [], | 
| 11 |  | -		entries: { | 
| 12 |  | -			identifier: string; | 
| 13 |  | -			presences: string[]; | 
| 14 |  | -			platform: { os: string; arch: string }; | 
| 15 |  | -			updated: number; | 
| 16 |  | -		}[] = []; | 
| 17 |  | - | 
| 18 |  | -	for (const u of scienceUpdates) { | 
| 19 |  | -		try { | 
| 20 |  | -			const e = JSON.parse(u); | 
| 21 |  | - | 
| 22 |  | -			entries.push({ | 
| 23 |  | -				identifier: e.identifier, | 
| 24 |  | -				presences: e.presences, | 
| 25 |  | -				platform: { | 
| 26 |  | -					arch: e.platform.arch, | 
| 27 |  | -					os: e.platform.os | 
| 28 |  | -				}, | 
| 29 |  | -				updated: Date.now() | 
| 30 |  | -			}); | 
| 31 |  | -		} catch (e) { | 
| 32 |  | -			invalidEntries.push(u); | 
| 33 |  | -			//* Invalid entry | 
|  | 7 | +	return limit(async () => { | 
|  | 8 | +		const log = mainLog.extend("updateScience"), | 
|  | 9 | +			key = "pmd-api.scienceUpdates"; | 
|  | 10 | + | 
|  | 11 | +		log("Updating..."); | 
|  | 12 | +		const scienceUpdates = await redis.hvals(key); | 
|  | 13 | + | 
|  | 14 | +		let invalidEntries = [], | 
|  | 15 | +			entries = []; | 
|  | 16 | + | 
|  | 17 | +		for (const u of scienceUpdates) { | 
|  | 18 | +			try { | 
|  | 19 | +				const e = JSON.parse(u); | 
|  | 20 | + | 
|  | 21 | +				entries.push({ | 
|  | 22 | +					identifier: e.identifier, | 
|  | 23 | +					presences: e.presences, | 
|  | 24 | +					platform: { | 
|  | 25 | +						arch: e.platform.arch, | 
|  | 26 | +						os: e.platform.os | 
|  | 27 | +					}, | 
|  | 28 | +					updated: Date.now() | 
|  | 29 | +				}); | 
|  | 30 | +			} catch (e) { | 
|  | 31 | +				invalidEntries.push(u); | 
|  | 32 | +			} | 
| 34 | 33 | 		} | 
| 35 |  | -	} | 
| 36 |  | - | 
| 37 |  | -	if (invalidEntries.length) { | 
| 38 |  | -		await redis.hdel(key, ...invalidEntries); | 
| 39 |  | -		log("Deleted %n invalid entries", invalidEntries.length); | 
| 40 |  | -	} | 
| 41 |  | - | 
| 42 |  | -	if (entries.length) { | 
| 43 |  | -		const res = await mongo | 
| 44 |  | -			.db("PreMiD") | 
| 45 |  | -			.collection("science") | 
| 46 |  | -			.bulkWrite( | 
| 47 |  | -				entries.map(e => ({ | 
| 48 |  | -					updateOne: { | 
| 49 |  | -						filter: { identifier: e.identifier }, | 
| 50 |  | -						update: { $set: e }, | 
| 51 |  | -						upsert: true | 
| 52 |  | -					} | 
| 53 |  | -				})) | 
| 54 |  | -			); | 
| 55 |  | - | 
| 56 |  | -		await redis.hdel(key, ...entries.map(e => e.identifier)); | 
| 57 |  | - | 
| 58 |  | -		log( | 
| 59 |  | -			"Inserted %s entries, Updated %s entries", | 
| 60 |  | -			res.upsertedCount, | 
| 61 |  | -			res.modifiedCount | 
| 62 |  | -		); | 
| 63 |  | -	} else log("No entries to update"); | 
| 64 |  | - | 
| 65 |  | -	const delRedis = await redis.hvals("pmd-api.scienceDeletes"); | 
| 66 |  | - | 
| 67 |  | -	let orMatch: any[] = [ | 
| 68 |  | -		{ | 
| 69 |  | -			updated: { $lt: Date.now() - 31 * 24 * 60 * 60 * 1000 } | 
|  | 34 | + | 
|  | 35 | +		if (invalidEntries.length) { | 
|  | 36 | +			await redis.hdel(key, ...invalidEntries); | 
|  | 37 | +			log("Deleted %n invalid entries", invalidEntries.length); | 
| 70 | 38 | 		} | 
| 71 |  | -	]; | 
| 72 | 39 | 
 | 
| 73 |  | -	if (delRedis.length) orMatch.push({ identifier: { $in: delRedis } }); | 
|  | 40 | +		if (entries.length) { | 
|  | 41 | +			const bulkOps = entries.map(e => ({ | 
|  | 42 | +				updateOne: { | 
|  | 43 | +					filter: { identifier: e.identifier }, | 
|  | 44 | +					update: { $set: e }, | 
|  | 45 | +					upsert: true | 
|  | 46 | +				} | 
|  | 47 | +			})); | 
| 74 | 48 | 
 | 
| 75 |  | -	const delRes = await mongo.db("PreMiD").collection("science").deleteMany({ | 
| 76 |  | -		$or: orMatch | 
| 77 |  | -	}); | 
|  | 49 | +			// Batch the bulk operations for better performance | 
|  | 50 | +			const BATCH_SIZE = 1000; | 
|  | 51 | +			for (let i = 0; i < bulkOps.length; i += BATCH_SIZE) { | 
|  | 52 | +				const batch = bulkOps.slice(i, i + BATCH_SIZE); | 
|  | 53 | +				const res = await mongo | 
|  | 54 | +					.db("PreMiD") | 
|  | 55 | +					.collection("science") | 
|  | 56 | +					.bulkWrite(batch); | 
|  | 57 | +				log( | 
|  | 58 | +					"Batch %s: Inserted %s entries, Updated %s entries", | 
|  | 59 | +					Math.floor(i / BATCH_SIZE) + 1, | 
|  | 60 | +					res.upsertedCount, | 
|  | 61 | +					res.modifiedCount | 
|  | 62 | +				); | 
|  | 63 | +			} | 
|  | 64 | + | 
|  | 65 | +			await redis.hdel(key, ...entries.map(e => e.identifier)); | 
|  | 66 | +		} else { | 
|  | 67 | +			log("No entries to update"); | 
|  | 68 | +		} | 
| 78 | 69 | 
 | 
| 79 |  | -	if (delRedis.length) await redis.hdel("pmd-api.scienceDeletes", ...delRedis); | 
|  | 70 | +		const delRedis = await redis.hvals("pmd-api.scienceDeletes"); | 
| 80 | 71 | 
 | 
| 81 |  | -	if (delRes.deletedCount) log("Deleted %s entries", delRes.deletedCount); | 
|  | 72 | +		let orMatch: any[] = [ | 
|  | 73 | +			{ | 
|  | 74 | +				updated: { $lt: Date.now() - 31 * 24 * 60 * 60 * 1000 } | 
|  | 75 | +			} | 
|  | 76 | +		]; | 
|  | 77 | + | 
|  | 78 | +		if (delRedis.length) { | 
|  | 79 | +			orMatch.push({ identifier: { $in: delRedis } }); | 
|  | 80 | +		} | 
|  | 81 | + | 
|  | 82 | +		const delCollection = mongo.db("PreMiD").collection("science"); | 
|  | 83 | + | 
|  | 84 | +		const delRes = await delCollection.deleteMany({ | 
|  | 85 | +			$or: orMatch | 
|  | 86 | +		}); | 
|  | 87 | + | 
|  | 88 | +		if (delRedis.length) { | 
|  | 89 | +			await redis.hdel("pmd-api.scienceDeletes", ...delRedis); | 
|  | 90 | +		} | 
|  | 91 | + | 
|  | 92 | +		if (delRes.deletedCount) { | 
|  | 93 | +			log("Deleted %s entries", delRes.deletedCount); | 
|  | 94 | +		} | 
|  | 95 | +	}); | 
| 82 | 96 | } | 
0 commit comments