From f3ea6862aa9fafa462355fadb5d1ad042f4c707f Mon Sep 17 00:00:00 2001 From: Eric Merrill Date: Mon, 14 Mar 2022 22:56:20 -0400 Subject: [PATCH] MDL-74183 completion: Protect against index conflict in cron --- lib/classes/task/completion_daily_task.php | 36 +++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/lib/classes/task/completion_daily_task.php b/lib/classes/task/completion_daily_task.php index b7966bfd6a5..314f78a3bba 100644 --- a/lib/classes/task/completion_daily_task.php +++ b/lib/classes/task/completion_daily_task.php @@ -121,10 +121,40 @@ class completion_daily_task extends scheduled_task { if ($prev->completionid) { $completion->id = $prev->completionid; } - $completion->mark_enrolled(); - if (debugging()) { - mtrace('Marked started user ' . $prev->userid . ' in course ' . $prev->course); + try { + $completion->mark_enrolled(); + + if (debugging()) { + mtrace('Marked started user '.$prev->userid.' in course '.$prev->course); + } + } catch (\dml_write_exception $e) { + // Most likely this happened because the completion object was created while we were working. + // So get the record and make sure it has a time enrolled set. + if (debugging()) { + mtrace('Exception while marking started user '.$prev->userid.' in course '.$prev->course.', retrying'); + } + + $params = ['userid' => $completion->userid, 'course' => $completion->course]; + $existing = new \completion_completion($params); + if (!empty($existing->id) && empty($existing->timeenrolled)) { + $existing->timeenrolled = $completion->timeenrolled; + try { + $existing->mark_enrolled(); + } catch (\Exception $e) { + // Catch everything, so we can continue on to other records. + if (debugging()) { + mtrace('Exception again while marking started user '.$prev->userid.' in course '.$prev->course. + ': '.$e->getMessage()."\n".$e->getTraceAsString()); + } + } + } + } catch (\Exception $e) { + // Catch anything else, so we can continue on to other records. + if (debugging()) { + mtrace('Exception while marking started user '.$prev->userid.' in course '.$prev->course. + ': '.$e->getMessage()."\n".$e->getTraceAsString()); + } } } else if ($prev && $current) { // Else, if this record is for the same user/course use oldest timeenrolled. -- 2.11.4.GIT