/** * will select a previously unprocessed set of snapshot items * * @return array: <id> => array with values */ public function getNextChunk($is_bulk, $is_test) { $chunk_size = CRM_Donrec_Logic_Settings::getChunkSize(); $snapshot_id = $this->getId(); $chunk = array(); if ($is_test) { $status_clause = "`status` IS NULL"; } else { $status_clause = "(`status` IS NULL OR `status`='TEST')"; } // here, we need a different algorithm for bulk than for single: if (empty($is_bulk)) { // SINGLE case: just grab $chunk_size items $query = "SELECT * FROM `donrec_snapshot` WHERE `snapshot_id` = {$snapshot_id} AND {$status_clause} LIMIT {$chunk_size};"; $result = CRM_Core_DAO::executeQuery($query); while ($result->fetch()) { $chunk_line = array(); foreach (self::$CHUNK_FIELDS as $field) { $chunk_line[$field] = $result->{$field}; } $chunk[$chunk_line['id']] = $chunk_line; } } else { // BULK case: get items grouped by contact ID until it exceeds $chunk_size // get all lines $query = "SELECT\n snapshot.*,\n a.contrib_count\n FROM\n `donrec_snapshot` AS snapshot,\n (SELECT `contact_id`, COUNT(*) AS contrib_count\n FROM `donrec_snapshot`\n GROUP BY `contact_id`) AS a\n WHERE a.`contact_id` = snapshot.`contact_id`\n AND snapshot.`snapshot_id` = {$snapshot_id}\n AND {$status_clause}\n ORDER BY snapshot.`contact_id` ASC;"; $query = CRM_Core_DAO::executeQuery($query); $last_added_contact_id = NULL; $contribution_count = 0; while ($query->fetch()) { if ($last_added_contact_id != $query->contact_id) { // this is a new contact ID if (count($chunk) >= $chunk_size || $contribution_count > 5 * $chunk_size) { // we already have $chunk_size contacts, or 5x $chunk_size contributions // => that's enough for this chunk! break; } // ok, we're still under the limit => create a section for the contact $chunk[$query->contact_id] = array(); $last_added_contact_id = $query->contact_id; } // add contribution $contribution = array(); foreach (self::$CHUNK_FIELDS as $field) { $contribution[$field] = $query->{$field}; } $chunk[$query->contact_id][] = $contribution; $contribution_count += 1; } } // reset the process information for the given chunk $this->resetChunk($chunk, $is_bulk); if (count($chunk) == 0) { return NULL; } else { return $chunk; } }
/** * Get a batching lock * * the lock is needed so that only one relevant process can access the * payment/statment data structures at a time * * @return lock object. check if it ->isAcquired() before use */ public static function getLock($type, $id) { if ($type == '') { // for the 'next' lock, we calculate the lock timeout as follows $max_lock_timeout = ini_get('max_execution_time'); if (empty($max_lock_timeout)) { $max_lock_timeout = 30 * 60; // 30 minutes } // calculate based on chunk size (max 1min/item) $calculation_time = CRM_Donrec_Logic_Settings::getChunkSize() * 60; $timeout = min($calculation_time, $max_lock_timeout); } else { // default timeout for other locks $timeout = 600.0; // 10mins, TODO: do we need a setting here? } //CRM_Core_Error::debug_log_message("de.systopia.donrec.$type".'-'.$id." timeout $timeout created."); return CRM_Utils_DonrecSafeLock::acquireLock("de.systopia.donrec.{$type}" . '-' . $id, $timeout); }