Skip to content

Commit

Permalink
course_mosule based adhoc task, limit and batchsize
Browse files Browse the repository at this point in the history
  • Loading branch information
rajandangi committed Jun 16, 2024
1 parent 55c7ed0 commit 533cd99
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 70 deletions.
40 changes: 21 additions & 19 deletions classes/task/reengagement_adhoc_task.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,18 @@ public function execute() {
global $DB;

$data = $this->get_custom_data();
if (empty($data)) {
return;
}

// mtrace('Data: ' . print_r($data, true));
// Get a list of users who are eligible to start this module.
$startusers = reengagement_get_startusers($data);
if (empty($startusers)) {
mtrace("No users found to start reengagementid " . $data->rid);
return;
}

//Fetch the Reengagement based on the provided id
// $reengagementcm = $DB->get_record('course_modules', ['id' => $data->cmid]);
// if (!$reengagementcm) {
// return;
// }
// mtrace('Reengagement: ' . print_r($reengagementcm, true));
// die;
// Prepare the objects for db iteratin
// Prepare the objects for db iteratin.
$timenow = time();
$reengagementinprogress = new stdClass();
$reengagementinprogress->reengagement = $data->rid;
Expand All @@ -67,18 +68,19 @@ public function execute() {
$activitycompletion->completionstate = COMPLETION_INCOMPLETE;
$activitycompletion->timemodified = $timenow;

// Define the counter.
$newripcount = 0;
foreach (reengagement_get_startusers($data) as $startcandidate) {
$reengagementinprogress->userid = $startcandidate->id;
$DB->insert_record('reengagement_inprogress', $reengagementinprogress);
$activitycompletion->userid = $startcandidate->id;
$DB->insert_record('course_modules_completion', $activitycompletion);
$newripcount++;
}
// Start reengagement for each user.
$userlist = array_keys($startusers);
$newripcount = count($userlist); // Count of new reengagements in progress.

if (debugging('', DEBUG_DEVELOPER) || ($newripcount && debugging('', DEBUG_ALL))) {
mtrace("Adding $newripcount reengagements-in-progress to reengagementid " . $data->rid);
mtrace("Found $newripcount users to start reengagementid " . $data->rid);
}

foreach ($userlist as $userid) {
$reengagementinprogress->userid = $userid;
$DB->insert_record('reengagement_inprogress', $reengagementinprogress);
$activitycompletion->userid = $userid;
$DB->insert_record('course_modules_completion', $activitycompletion);
}

// Process completed reengagements.
Expand Down
90 changes: 39 additions & 51 deletions lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,28 +187,6 @@ function reengagement_crontask() {
mtrace("Adding adhoc task for course module id " . $reengagementcm->cmid);
}
reengagement_queue_adhoc_task($reengagementcm);
// Prepare some objects for later db insertion.
// $reengagementinprogress = new stdClass();
// $reengagementinprogress->reengagement = $reengagementcm->rid;
// $reengagementinprogress->completiontime = $timenow + $reengagementcm->duration;
// $reengagementinprogress->emailtime = $timenow + $reengagementcm->emaildelay;
// $activitycompletion = new stdClass();
// $activitycompletion->coursemoduleid = $reengagementcm->cmid;
// $activitycompletion->completionstate = COMPLETION_INCOMPLETE;
// $activitycompletion->timemodified = $timenow;

// $newripcount = 0;
// foreach (reengagement_get_startusers($reengagementcm) as $startcandidate) {
// $reengagementinprogress->userid = $startcandidate->id;
// $DB->insert_record('reengagement_inprogress', $reengagementinprogress);
// $activitycompletion->userid = $startcandidate->id;
// $DB->insert_record('course_modules_completion', $activitycompletion);
// $newripcount++;
// }

// if (debugging('', DEBUG_DEVELOPER) || ($newripcount && debugging('', DEBUG_ALL))) {
// mtrace("Adding $newripcount reengagements-in-progress to reengagementid " . $reengagementcm->rid);
// }
}
return true;
}
Expand Down Expand Up @@ -562,51 +540,61 @@ function reengagement_reset_userdata($data) {
* Get array of users who can start supplied reengagement module
*
* @param object $reengagement - reengagement record.
* @return Generator
* @param $batchsize - number of users to return in each batch.
* @return array - array of user records.
*/
function reengagement_get_startusers($reengagement) {
function reengagement_get_startusers($reengagement, $batchsize = 1000) {
global $DB;
$context = context_module::instance($reengagement->cmid);

list($esql, $params) = get_enrolled_sql($context, 'mod/reengagement:startreengagement', 0, true);

// Get a list of people who already started this reengagement (finished users are included in this list)
// (based on activity completion records).
$alreadycompletionsql = "SELECT userid
FROM {course_modules_completion}
WHERE coursemoduleid = :alcmoduleid";
$params['alcmoduleid'] = $reengagement->cmid;

// Get a list of people who already started this reengagement
// (based on reengagement_inprogress records).
$alreadyripsql = "SELECT userid
FROM {reengagement_inprogress}
WHERE reengagement = :ripmoduleid";
$params['ripmoduleid'] = $reengagement->rid;

$sql = "SELECT u.*
FROM {user} u
JOIN ($esql) je ON je.id = u.id
LEFT JOIN {course_modules_completion} cmc ON cmc.userid = u.id AND cmc.coursemoduleid = :alcmoduleid
LEFT JOIN {reengagement_inprogress} rip ON rip.userid = u.id AND rip.reengagement = :ripmoduleid
WHERE u.deleted = 0
AND u.confirmed = 1
AND cmc.id IS NULL
AND rip.id IS NULL";

$params['alcmoduleid'] = $reengagement->cmid;
$params['ripmoduleid'] = $reengagement->rid;
WHERE u.deleted = 0
AND u.id NOT IN ($alreadycompletionsql)
AND u.id NOT IN ($alreadyripsql)";

// Load modinfo once per course and cache it to avoid multiple calls to get_fast_modinfo.
$modinfo = get_fast_modinfo($reengagement->courseid);
$cm = $modinfo->get_cm($reengagement->cmid);
$ainfomod = new \core_availability\info_module($cm);
$information = '';

// Get all users.
$start = 0;
while (true) {
$startusers = $DB->get_records_sql($sql, $params, $start, 1000);
if (empty($startusers)) {
break;
}
// TODO: can we get rid of this loop by adding other required conditions to the SQL itself?
// Can we store availability info in the reengagement_inprogress table beforehand?
// For e.g. on module create,update,delete, user enrolment etc.
foreach ($startusers as $startcandidate) {

if ($ainfomod->is_available($information, false, $startcandidate->id, $modinfo)) {
yield $startcandidate;
}
// Define a key.
$configkey = 'reengagement_start_cmid_' . $reengagement->cmid;
$start = get_config('mod_reengagement', $configkey) ?: 0;

$startusers = $DB->get_records_sql($sql, $params, $start, $batchsize);
$startcandidates = array_filter($startusers, function ($startcandidate) use ($modinfo, $cm) {
if (empty($startcandidate->confirmed)) {
return false;
}
$start += 1000;
$ainfomod = new \core_availability\info_module($cm);
$information = '';
return $ainfomod->is_available($information, false, $startcandidate->id, $modinfo);
});

if (count($startusers) < $batchsize) {
set_config($configkey, 0, 'mod_reengagement'); // We have reached the end of the list.
} else {
// There are more users to process in next turn.
set_config($configkey, $start + $batchsize, 'mod_reengagement');
}
return $startcandidates;
}


Expand Down

0 comments on commit 533cd99

Please sign in to comment.