Skip to content

Conversation

meisterT
Copy link
Member

@meisterT meisterT commented Sep 6, 2025

Previous buggy flow was something like:

  • fetch all submissions that for this team/contest/problem combination
  • that are valid
  • and have a valid judging

The idea of

->leftJoin('s.judgings', 'j', Join::WITH, 'j.valid = 1')
was that this would filter the OneToMany collection down to only valid judgings. This is also what happens on the database side.

However, on the doctrine side, the entity manager keeps a cache, and if the submission is already in the cache with the full collection of valid and invalid judgings, it will only merged with new data from the database query, no data (i.e. no judgings) will magically disappear.

In order to fix this, we explicitly filter on the PHP side. An alternative would be to add a new OneToMany mapping with a where on it and use that.

Fixes #2883

Previous buggy flow was something like:
- fetch all submissions that for this team/contest/problem combination
- that are valid
- and have a valid judging

The idea of https://github.com/DOMjudge/domjudge/blob/95df1de7bce91f43600cfcb8760ea85762936614/webapp/src/Service/ScoreboardService.php#L240
was that this would filter the OneToMany collection down to only valid
judgings. This is also what happens on the database side.

However, on the doctrine side, the entity manager keeps a cache, and if
the submission is already in the cache with the full collection of valid
and invalid judgings, it will only merged with new data from the
database query, no data (i.e. no judgings) will magically disappear.

In order to fix this, we explicitly filter on the PHP side. An
alternative would be to add a new `OneToMany` mapping with a `where` on
it and use that.

Fixes DOMjudge#2883
@vmcj
Copy link
Member

vmcj commented Sep 7, 2025

Why is it so hard (or expensive) to fix this in the DB side? I miss that comment currently.

@meisterT
Copy link
Member Author

meisterT commented Sep 7, 2025

In order to fix this, we explicitly filter on the PHP side. An alternative would be to add a new OneToMany mapping with a where on it and use that.

I am not aware of any fix on the DB side. We could decide to switch off doctrine or disable any entity caching which would cost performance.

In case you are refering to what I wrote in the commit description:

In order to fix this, we explicitly filter on the PHP side. An alternative would be to add a new OneToMany mapping with a where on it and use that.

The two options are relatively equal. I picked filtering on the PHP side since 99% of submissions have 1 judging, so it is very cheap to do so. The other solution would not change the DB but allow us to to do an implicit DB query but it would require a migration.

Comment on lines +364 to +369
foreach ($this->judgings as $j) {
if ($j->getValid()) {
return $j;
}
}
return null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
foreach ($this->judgings as $j) {
if ($j->getValid()) {
return $j;
}
}
return null;
return $this->judgings->findFirst(fn(Judging $j) => $j->getValid());

maybe?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Rejudged solution not properly taken into account in the scoreboard
3 participants