From a0c8be84b24c4d7493146cc7637b6cfc9dd5e7e7 Mon Sep 17 00:00:00 2001 From: Edoardo Morassutto Date: Mon, 11 Nov 2019 18:21:18 +0100 Subject: [PATCH 1/4] Ignore wrong contest submissions in ProxyService When you are running cms with more than a contest (ie multicontest) ProxyService can be notified by ScoringService of new submissions of any contest, ignoring the `-c X` flag of PS. This will lead to `Inconsistent Data` errors in RWS due to submissions of the wrong contest (bad user, bad task, ...). This is especially bad because the wrong submission can be sent with other valid submissions, and RWS drop them all. The proposed fix just ignores those submissions from ProxyService since ScoringService has no way to know which contest PS is bound to. --- cms/service/ProxyService.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cms/service/ProxyService.py b/cms/service/ProxyService.py index 0d1b56ec3c..14041a7e79 100644 --- a/cms/service/ProxyService.py +++ b/cms/service/ProxyService.py @@ -9,6 +9,7 @@ # Copyright © 2015 Luca Versari # Copyright © 2015 William Di Luigi # Copyright © 2016 Amir Keivan Mohtashami +# Copyright © 2019 Edoardo Morassutto # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -386,6 +387,10 @@ def operations_for_score(self, submission): queues for them to be sent to rankings. """ + # ScoringService sent us a submission of another contest. + if submission.task.contest_id != self.contest_id: + return [] + submission_result = submission.get_result() # Data to send to remote rankings. @@ -422,6 +427,9 @@ def operations_for_token(self, submission): queues for them to be sent to rankings. """ + # ScoringService sent us a submission of another contest. + if submission.task.contest_id != self.contest_id: + return [] # Data to send to remote rankings. submission_id = "%d" % submission.id submission_data = { From fe0d48f525ac07b5a5329c61842b5d360227758d Mon Sep 17 00:00:00 2001 From: Edoardo Morassutto Date: Sat, 11 Dec 2021 17:28:35 +0100 Subject: [PATCH 2/4] Move the contest_id checks in submission_scored/tokened --- cms/service/ProxyService.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/cms/service/ProxyService.py b/cms/service/ProxyService.py index 14041a7e79..3feed45a43 100644 --- a/cms/service/ProxyService.py +++ b/cms/service/ProxyService.py @@ -387,10 +387,6 @@ def operations_for_score(self, submission): queues for them to be sent to rankings. """ - # ScoringService sent us a submission of another contest. - if submission.task.contest_id != self.contest_id: - return [] - submission_result = submission.get_result() # Data to send to remote rankings. @@ -427,9 +423,6 @@ def operations_for_token(self, submission): queues for them to be sent to rankings. """ - # ScoringService sent us a submission of another contest. - if submission.task.contest_id != self.contest_id: - return [] # Data to send to remote rankings. submission_id = "%d" % submission.id submission_data = { @@ -496,6 +489,11 @@ def submission_scored(self, submission_id): submission_id) return + # ScoringService sent us a submission of another contest, they + # do not know about our contest_id in multicontest setup. + if submission.task.contest_id != self.contest_id: + return + # Update RWS. for operation in self.operations_for_score(submission): self.enqueue(operation) @@ -531,6 +529,11 @@ def submission_tokened(self, submission_id): submission_id) return + # ScoringService sent us a submission of another contest, they + # do not know about our contest_id in multicontest setup. + if submission.task.contest_id != self.contest_id: + return + # Update RWS. for operation in self.operations_for_token(submission): self.enqueue(operation) From 326375ee79237c8f4e7ed5ac5d408cea7712f18d Mon Sep 17 00:00:00 2001 From: Edoardo Morassutto Date: Mon, 13 Dec 2021 18:30:09 +0100 Subject: [PATCH 3/4] Move PS contest checks before submission validation Filter out the submissions from the wrong contest before rejecting them if they are hidden/unofficial. Add also some debug logging when it happens. This also adds the check in dataset_updated() since AWS may trigger the same kind of wrong RWS notifications. --- cms/service/ProxyService.py | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/cms/service/ProxyService.py b/cms/service/ProxyService.py index 3feed45a43..ab37a1e060 100644 --- a/cms/service/ProxyService.py +++ b/cms/service/ProxyService.py @@ -477,6 +477,14 @@ def submission_scored(self, submission_id): "unexistent submission id %s.", submission_id) raise KeyError("Submission not found.") + # ScoringService sent us a submission of another contest, they + # do not know about our contest_id in multicontest setup. + if submission.task.contest_id != self.contest_id: + logger.debug("Ignoring submission %s of contest %d " + "(this ProxyService considers contest %d only)", + submission.id, submission.task.contest_id, self.contest_id) + return + if submission.participation.hidden: logger.info("[submission_scored] Score for submission %d " "not sent because the participation is hidden.", @@ -489,11 +497,6 @@ def submission_scored(self, submission_id): submission_id) return - # ScoringService sent us a submission of another contest, they - # do not know about our contest_id in multicontest setup. - if submission.task.contest_id != self.contest_id: - return - # Update RWS. for operation in self.operations_for_score(submission): self.enqueue(operation) @@ -517,6 +520,14 @@ def submission_tokened(self, submission_id): "unexistent submission id %s.", submission_id) raise KeyError("Submission not found.") + # ScoringService sent us a submission of another contest, they + # do not know about our contest_id in multicontest setup. + if submission.task.contest_id != self.contest_id: + logger.debug("Ignoring submission %s of contest %d " + "(this ProxyService considers contest %d only)", + submission.id, submission.task.contest_id, self.contest_id) + return + if submission.participation.hidden: logger.info("[submission_tokened] Token for submission %d " "not sent because participation is hidden.", @@ -529,11 +540,6 @@ def submission_tokened(self, submission_id): submission_id) return - # ScoringService sent us a submission of another contest, they - # do not know about our contest_id in multicontest setup. - if submission.task.contest_id != self.contest_id: - return - # Update RWS. for operation in self.operations_for_token(submission): self.enqueue(operation) @@ -556,6 +562,14 @@ def dataset_updated(self, task_id): task = Task.get_from_id(task_id, session) dataset = task.active_dataset + # This ProxyService may focus on a different contest, and it should + # ignore this update. + if task.contest_id != self.contest_id: + logger.debug("Ignoring dataset change for task %d of contest %d " + "(this ProxyService considers contest %d only)", + task_id, task.contest.id, self.contest_id) + return + logger.info("Dataset update for task %d (dataset now is %d).", task.id, dataset.id) From 0327b85b066e4e728e7469e6cdb13f3fda274a5d Mon Sep 17 00:00:00 2001 From: Edoardo Morassutto Date: Thu, 16 Dec 2021 21:10:55 +0100 Subject: [PATCH 4/4] Fix line lengths and message format --- cms/service/ProxyService.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/cms/service/ProxyService.py b/cms/service/ProxyService.py index ab37a1e060..68b30271ab 100644 --- a/cms/service/ProxyService.py +++ b/cms/service/ProxyService.py @@ -480,9 +480,10 @@ def submission_scored(self, submission_id): # ScoringService sent us a submission of another contest, they # do not know about our contest_id in multicontest setup. if submission.task.contest_id != self.contest_id: - logger.debug("Ignoring submission %s of contest %d " - "(this ProxyService considers contest %d only)", - submission.id, submission.task.contest_id, self.contest_id) + logger.debug("Ignoring submission %d of contest %d " + "(this ProxyService considers contest %d only).", + submission.id, submission.task.contest_id, + self.contest_id) return if submission.participation.hidden: @@ -523,9 +524,10 @@ def submission_tokened(self, submission_id): # ScoringService sent us a submission of another contest, they # do not know about our contest_id in multicontest setup. if submission.task.contest_id != self.contest_id: - logger.debug("Ignoring submission %s of contest %d " - "(this ProxyService considers contest %d only)", - submission.id, submission.task.contest_id, self.contest_id) + logger.debug("Ignoring submission %d of contest %d " + "(this ProxyService considers contest %d only).", + submission.id, submission.task.contest_id, + self.contest_id) return if submission.participation.hidden: @@ -565,9 +567,10 @@ def dataset_updated(self, task_id): # This ProxyService may focus on a different contest, and it should # ignore this update. if task.contest_id != self.contest_id: - logger.debug("Ignoring dataset change for task %d of contest %d " - "(this ProxyService considers contest %d only)", - task_id, task.contest.id, self.contest_id) + logger.debug("Ignoring dataset change for task %d of contest " + "%d (this ProxyService considers contest %d " + "only).", task_id, task.contest.id, + self.contest_id) return logger.info("Dataset update for task %d (dataset now is %d).",