From ce3cdc645c43a2b0ef848d1075ed8c9bbc02c30b Mon Sep 17 00:00:00 2001 From: undefined Date: Mon, 21 Jun 2021 18:04:49 +0800 Subject: [PATCH] vjudge: prevent race cond --- packages/vjudge/package.json | 2 +- packages/vjudge/src/model.ts | 26 ++++++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/packages/vjudge/package.json b/packages/vjudge/package.json index 0313c006..978757e4 100644 --- a/packages/vjudge/package.json +++ b/packages/vjudge/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/vjudge", - "version": "1.0.4", + "version": "1.0.5", "description": "Submit problems to remote oj", "main": "package.json", "repository": "https://github.com/hydro-dev/Hydro.git", diff --git a/packages/vjudge/src/model.ts b/packages/vjudge/src/model.ts index 0ec41958..6422aaf5 100644 --- a/packages/vjudge/src/model.ts +++ b/packages/vjudge/src/model.ts @@ -13,6 +13,7 @@ import { BasicProvider, IBasicProvider, RemoteAccount } from './interface'; const coll = db.collection('vjudge'); const Pool = {}; const logger = new Logger('vjudge'); +const syncing = {}; class Service { api: IBasicProvider; @@ -37,17 +38,22 @@ class Service { while (pids.length) { logger.info(`${domainId}: Syncing page ${page}`); for (const pid of pids) { - if (await ProblemModel.get(domainId, pid)) continue; - const res = await this.api.getProblem(pid); - if (!res) continue; - const id = await ProblemModel.add(domainId, pid, res.title, res.content, 1, res.tag, false); - for (const key in res.files) { - await ProblemModel.addAdditionalFile(domainId, id, key, res.files[key]); + if (syncing[`${domainId}/${pid}`] || await ProblemModel.get(domainId, pid)) continue; + syncing[`${domainId}/${pid}`] = true; + try { + const res = await this.api.getProblem(pid); + if (!res) continue; + const id = await ProblemModel.add(domainId, pid, res.title, res.content, 1, res.tag, false); + for (const key in res.files) { + await ProblemModel.addAdditionalFile(domainId, id, key, res.files[key]); + } + for (const key in res.data) { + await ProblemModel.addTestdata(domainId, id, key, res.data[key]); + } + logger.info(`${domainId}: problem ${id} sync done`); + } finally { + delete syncing[`${domainId}/${pid}`]; } - for (const key in res.data) { - await ProblemModel.addTestdata(domainId, id, key, res.data[key]); - } - logger.info(`${domainId}: problem ${id} sync done`); await sleep(5000); } page++;