/** * Initiate all pending/ready jobs * * @param array $testParams * @param null $mode * * @return void */ public static function runJobs($testParams = NULL, $mode = NULL) { $job = new CRM_Mailing_BAO_MailingJob(); $config = CRM_Core_Config::singleton(); $jobTable = CRM_Mailing_DAO_MailingJob::getTableName(); $mailingTable = CRM_Mailing_DAO_Mailing::getTableName(); if (!empty($testParams)) { $query = "\n SELECT *\n FROM {$jobTable}\n WHERE id = {$testParams['job_id']}"; $job->query($query); } else { $currentTime = date('YmdHis'); $mailingACL = CRM_Mailing_BAO_Mailing::mailingACL('m'); $domainID = CRM_Core_Config::domainID(); $modeClause = 'AND m.sms_provider_id IS NULL'; if ($mode == 'sms') { $modeClause = 'AND m.sms_provider_id IS NOT NULL'; } // Select the first child job that is scheduled // CRM-6835 $query = "\n SELECT j.*\n FROM {$jobTable} j,\n {$mailingTable} m\n WHERE m.id = j.mailing_id AND m.domain_id = {$domainID}\n {$modeClause}\n AND j.is_test = 0\n AND ( ( j.start_date IS null\n AND j.scheduled_date <= {$currentTime}\n AND j.status = 'Scheduled' )\n OR ( j.status = 'Running'\n AND j.end_date IS null ) )\n AND (j.job_type = 'child')\n AND {$mailingACL}\n ORDER BY j.mailing_id,\n j.id\n "; $job->query($query); } while ($job->fetch()) { // still use job level lock for each child job $lockName = "civimail.job.{$job->id}"; $lock = new CRM_Core_Lock($lockName); if (!$lock->isAcquired()) { continue; } // for test jobs we do not change anything, since its on a short-circuit path if (empty($testParams)) { // we've got the lock, but while we were waiting and processing // other emails, this job might have changed under us // lets get the job status again and check $job->status = CRM_Core_DAO::getFieldValue('CRM_Mailing_DAO_MailingJob', $job->id, 'status', 'id', TRUE); if ($job->status != 'Running' && $job->status != 'Scheduled') { // this includes Cancelled and other statuses, CRM-4246 $lock->release(); continue; } } /* Queue up recipients for the child job being launched */ if ($job->status != 'Running') { $transaction = new CRM_Core_Transaction(); // have to queue it up based on the offset and limits // get the parent ID, and limit and offset $job->queue($testParams); // Mark up the starting time $saveJob = new CRM_Mailing_DAO_MailingJob(); $saveJob->id = $job->id; $saveJob->start_date = date('YmdHis'); $saveJob->status = 'Running'; $saveJob->save(); $transaction->commit(); } // Get the mailer // make it a persistent connection, CRM-9349 if ($mode === NULL) { $mailer = $config->getMailer(TRUE); } elseif ($mode == 'sms') { $mailer = CRM_SMS_Provider::singleton(array('mailing_id' => $job->mailing_id)); } // Compose and deliver each child job $isComplete = $job->deliver($mailer, $testParams); CRM_Utils_Hook::post('create', 'CRM_Mailing_DAO_Spool', $job->id, $isComplete); // Mark the child complete if ($isComplete) { /* Finish the job */ $transaction = new CRM_Core_Transaction(); $saveJob = new CRM_Mailing_DAO_MailingJob(); $saveJob->id = $job->id; $saveJob->end_date = date('YmdHis'); $saveJob->status = 'Complete'; $saveJob->save(); $transaction->commit(); // don't mark the mailing as complete } // Release the child joblock $lock->release(); if ($testParams) { return $isComplete; } } }