From ad2f985c3c2fbbae1d2b54ca99ea07d70c49b55a Mon Sep 17 00:00:00 2001 From: tobiichi3227 <86729076+tobiichi3227@users.noreply.github.com> Date: Sun, 15 Dec 2024 20:32:39 +0800 Subject: [PATCH] Fix: Connection handling, ranking order, SQL errors (#100) * fix: release all connection resources when server shutdown * fix: release redis connection when websocket closed * fix: problem rank should be ordered by score in descending order * fix: optimize inner join by including matching column The inner join should include the matching column; otherwise, the database will choose a sequential scan instead of an index scan. * fix(contests): sql syntax error * fix(pro): cannot load PDFJS * fix: escape markdown code content failed --- src/handlers/base.py | 11 +++++++++-- src/handlers/rank.py | 13 +++++++------ src/server.py | 10 +++++----- src/services/contests.py | 2 +- src/static/templ/pro.html | 2 +- src/utils/htmlgen.py | 2 +- 6 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/handlers/base.py b/src/handlers/base.py index 9f35a386..4ba22a91 100644 --- a/src/handlers/base.py +++ b/src/handlers/base.py @@ -82,9 +82,16 @@ def __init__(self, *args, **kwargs): def check_origin(self, _: str) -> bool: return True + async def cleanup(self): + await self.p.unsubscribe() + if self.task: + self.task.cancel() + + await self.p.aclose() + await self.rs.aclose() + def on_close(self) -> None: - self.task.cancel() - asyncio.create_task(self.rs.aclose()) + asyncio.create_task(self.cleanup()) def reqenv(func): diff --git a/src/handlers/rank.py b/src/handlers/rank.py index 33734a01..c7ba3af3 100644 --- a/src/handlers/rank.py +++ b/src/handlers/rank.py @@ -37,25 +37,26 @@ async def get(self, pro_id): "account"."name" AS "acct_name", "challenge_state"."runtime", "challenge_state"."memory", - ROUND("challenge_state"."rate", "problem"."rate_precision") + ROUND("challenge_state"."rate", "problem"."rate_precision") AS rate FROM "challenge" + + INNER JOIN "problem" + ON "challenge"."pro_id" = "problem"."pro_id" AND "problem"."pro_id" = $1 + INNER JOIN "account" ON "challenge"."acct_id"="account"."acct_id" INNER JOIN "challenge_state" ON "challenge"."chal_id"="challenge_state"."chal_id" - INNER JOIN "problem" - ON "challenge"."pro_id" = $1 - WHERE "challenge_state"."state"={ChalConst.STATE_AC} - ORDER BY "challenge"."acct_id" ASC, "challenge_state"."rate" ASC, + ORDER BY "challenge"."acct_id" ASC, "challenge_state"."rate" DESC, "challenge_state"."runtime" ASC, "challenge_state"."memory" ASC, "challenge"."timestamp" ASC ) temp - ORDER BY "runtime" ASC, "memory" ASC, + ORDER BY "rate" DESC, "runtime" ASC, "memory" ASC, "timestamp" ASC, "acct_id" ASC OFFSET $2 LIMIT $3; ''' , diff --git a/src/server.py b/src/server.py index 4dca6006..9445602a 100644 --- a/src/server.py +++ b/src/server.py @@ -33,11 +33,11 @@ def stop_loop(deadline): for task in asyncio.all_tasks(): task.cancel() - io_loop.add_callback(db.close) - io_loop.add_callback(rs.aclose) - io_loop.add_callback(pool.aclose) - io_loop.add_callback(JudgeServerClusterService.inst.disconnect_all_server) - io_loop.stop() + asyncio.create_task(db.close()) + asyncio.create_task(rs.aclose()) + asyncio.create_task(pool.aclose()) + asyncio.create_task(JudgeServerClusterService.inst.disconnect_all_server()) + io_loop.add_callback(io_loop.stop) print('Shutdown finally') diff --git a/src/services/contests.py b/src/services/contests.py index 381d1fd8..c922af11 100644 --- a/src/services/contests.py +++ b/src/services/contests.py @@ -247,7 +247,7 @@ async def get_ioi2013_scores(self, contest_id: int, pro_id: int, before_time: da "challenge"."pro_id", "challenge"."acct_id", "challenge"."timestamp", - ROUND("challenge_state"."rate", problem.rate_precision), + ROUND("challenge_state"."rate", problem.rate_precision) AS rate, ROW_NUMBER() OVER ( PARTITION BY "challenge"."pro_id", "challenge"."acct_id" diff --git a/src/static/templ/pro.html b/src/static/templ/pro.html index 32519765..e9bb3931 100644 --- a/src/static/templ/pro.html +++ b/src/static/templ/pro.html @@ -20,7 +20,7 @@ function init() { let PDFJS = pdfjsLib; - PDFJS.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.7.76/pdf.worker.min.mjs'; + PDFJS.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.7.76/pdf.worker.min.mjs'; $('#tags').keydown(function(event) { if (event.which == 13) // return diff --git a/src/utils/htmlgen.py b/src/utils/htmlgen.py index e54dc657..3f92f98f 100644 --- a/src/utils/htmlgen.py +++ b/src/utils/htmlgen.py @@ -17,4 +17,4 @@ def set_page_title(title: str, site_title: str = None): """ def markdown_escape(code: str) -> str: - return code.replace('`', '\\`').replace('\\', '\\\\') + return code.replace('\\', '\\\\').replace('`', '\\`')