尝试修复 submission 中的竞争问题
This commit is contained in:
23
contest/migrations/0010_auto_20190326_0201.py
Normal file
23
contest/migrations/0010_auto_20190326_0201.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 2.1.7 on 2019-03-26 02:01
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('contest', '0009_auto_20180501_0436'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='acmcontestrank',
|
||||||
|
unique_together={('user', 'contest')},
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='oicontestrank',
|
||||||
|
unique_together={('user', 'contest')},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -74,6 +74,7 @@ class ACMContestRank(AbstractContestRank):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "acm_contest_rank"
|
db_table = "acm_contest_rank"
|
||||||
|
unique_together = (("user", "contest"),)
|
||||||
|
|
||||||
|
|
||||||
class OIContestRank(AbstractContestRank):
|
class OIContestRank(AbstractContestRank):
|
||||||
@@ -84,6 +85,7 @@ class OIContestRank(AbstractContestRank):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "oi_contest_rank"
|
db_table = "oi_contest_rank"
|
||||||
|
unique_together = (("user", "contest"),)
|
||||||
|
|
||||||
|
|
||||||
class ContestAnnouncement(models.Model):
|
class ContestAnnouncement(models.Model):
|
||||||
|
|||||||
@@ -187,8 +187,9 @@ class JudgeDispatcher(DispatcherBase):
|
|||||||
logger.info(
|
logger.info(
|
||||||
"Contest debug mode, id: " + str(self.contest_id) + ", submission id: " + self.submission.id)
|
"Contest debug mode, id: " + str(self.contest_id) + ", submission id: " + self.submission.id)
|
||||||
return
|
return
|
||||||
self.update_contest_problem_status()
|
with transaction.atomic():
|
||||||
self.update_contest_rank()
|
self.update_contest_problem_status()
|
||||||
|
self.update_contest_rank()
|
||||||
else:
|
else:
|
||||||
if self.last_result:
|
if self.last_result:
|
||||||
self.update_problem_status_rejudge()
|
self.update_problem_status_rejudge()
|
||||||
@@ -329,29 +330,30 @@ class JudgeDispatcher(DispatcherBase):
|
|||||||
if self.contest.rule_type == ContestRuleType.OI or self.contest.real_time_rank:
|
if self.contest.rule_type == ContestRuleType.OI or self.contest.real_time_rank:
|
||||||
cache.delete(f"{CacheKey.contest_rank_cache}:{self.contest.id}")
|
cache.delete(f"{CacheKey.contest_rank_cache}:{self.contest.id}")
|
||||||
|
|
||||||
with transaction.atomic():
|
def get_rank(model):
|
||||||
if self.contest.rule_type == ContestRuleType.ACM:
|
return model.objects.select_for_update().get(user_id=self.submission.user_id, contest=self.contest)
|
||||||
model = ACMContestRank
|
|
||||||
func = self._update_acm_contest_rank
|
|
||||||
else:
|
|
||||||
model = OIContestRank
|
|
||||||
func = self._update_oi_contest_rank
|
|
||||||
|
|
||||||
|
if self.contest.rule_type == ContestRuleType.ACM:
|
||||||
|
model = ACMContestRank
|
||||||
|
func = self._update_acm_contest_rank
|
||||||
|
else:
|
||||||
|
model = OIContestRank
|
||||||
|
func = self._update_oi_contest_rank
|
||||||
|
|
||||||
|
try:
|
||||||
|
rank = get_rank(model)
|
||||||
|
except model.DoesNotExist:
|
||||||
try:
|
try:
|
||||||
# todo unique index
|
model.objects.create(user_id=self.submission.user_id, contest=self.contest)
|
||||||
# func 也不是安全的
|
rank = get_rank(model)
|
||||||
rank = model.objects.get(user_id=self.submission.user_id, contest=self.contest)
|
except IntegrityError:
|
||||||
except ACMContestRank.DoesNotExist:
|
rank = get_rank(model)
|
||||||
try:
|
func(rank)
|
||||||
rank = model.objects.create(user_id=self.submission.user_id, contest=self.contest)
|
|
||||||
except IntegrityError:
|
|
||||||
rank = model.objects.get(user_id=self.submission.user_id, contest=self.contest)
|
|
||||||
func(rank)
|
|
||||||
|
|
||||||
def _update_acm_contest_rank(self, rank):
|
def _update_acm_contest_rank(self, rank):
|
||||||
info = rank.submission_info.get(str(self.submission.problem_id))
|
info = rank.submission_info.get(str(self.submission.problem_id))
|
||||||
# 因前面更改过,这里需要重新获取
|
# 因前面更改过,这里需要重新获取
|
||||||
problem = Problem.objects.get(contest_id=self.contest_id, id=self.problem.id)
|
problem = Problem.objects.select_for_update().get(contest_id=self.contest_id, id=self.problem.id)
|
||||||
# 此题提交过
|
# 此题提交过
|
||||||
if info:
|
if info:
|
||||||
if info["is_ac"]:
|
if info["is_ac"]:
|
||||||
|
|||||||
Reference in New Issue
Block a user