/** * @param mixed $transports name of a single queue or array of queues to pull from * If not specified, checks all queues in the system. */ static function top($transports = null) { $qi = new Queue_item(); if ($transports) { if (is_array($transports)) { // @fixme use safer escaping $list = implode("','", array_map(array($qi, 'escape'), $transports)); $qi->whereAdd("transport in ('{$list}')"); } else { $qi->transport = $transports; } } $qi->orderBy('created'); $qi->whereAdd('claimed is null'); $qi->limit(1); $cnt = $qi->find(true); if ($cnt) { // XXX: potential race condition // can we force it to only update if claimed is still null // (or old)? common_log(LOG_INFO, 'claiming queue item id = ' . $qi->getID() . ' for transport ' . $qi->transport); $orig = clone $qi; $qi->claimed = common_sql_now(); $result = $qi->update($orig); if ($result) { common_log(LOG_INFO, 'claim succeeded.'); return $qi; } else { common_log(LOG_INFO, 'claim failed.'); } } $qi = null; return null; }
/** * Run a polling cycle during idle processing in the input loop. * @return boolean true if we should poll again for more data immediately */ public function poll() { $this->_log(LOG_DEBUG, 'Checking for notices...'); $qi = Queue_item::top($this->activeQueues()); if (empty($qi)) { $this->_log(LOG_DEBUG, 'No notices waiting; idling.'); return false; } $queue = $qi->transport; $item = $this->decode($qi->frame); if ($item) { $rep = $this->logrep($item); $this->_log(LOG_INFO, "Got {$rep} for transport {$queue}"); $handler = $this->getHandler($queue); if ($handler) { if ($handler->handle($item)) { $this->_log(LOG_INFO, "[{$queue}:{$rep}] Successfully handled item"); $this->_done($qi); } else { $this->_log(LOG_INFO, "[{$queue}:{$rep}] Failed to handle item"); $this->_fail($qi); } } else { $this->_log(LOG_INFO, "[{$queue}:{$rep}] No handler for queue {$queue}; discarding."); $this->_done($qi); } } else { $this->_log(LOG_INFO, "[{$queue}] Got empty/deleted item, discarding"); $this->_fail($qi); } return true; }
static function top($transport) { $qi = new Queue_item(); $qi->transport = $transport; $qi->orderBy('created'); $qi->whereAdd('claimed is null'); $qi->limit(1); $cnt = $qi->find(true); if ($cnt) { # XXX: potential race condition # can we force it to only update if claimed is still null # (or old)? common_log(LOG_INFO, 'claiming queue item = ' . $qi->notice_id . ' for transport ' . $transport); $orig = clone $qi; $qi->claimed = common_sql_now(); $result = $qi->update($orig); if ($result) { common_log(LOG_INFO, 'claim succeeded.'); return $qi; } else { common_log(LOG_INFO, 'claim failed.'); } } $qi = null; return null; }
function common_enqueue_notice($notice) { foreach (array('jabber', 'omb', 'sms', 'public', 'twitter', 'facebook', 'ping') as $transport) { $qi = new Queue_item(); $qi->notice_id = $notice->id; $qi->transport = $transport; $qi->created = $notice->created; $result = $qi->insert(); if (!$result) { $last_error =& PEAR::getStaticProperty('DB_DataObject', 'lastError'); common_log(LOG_ERR, 'DB error inserting queue item: ' . $last_error->message); return false; } common_log(LOG_DEBUG, 'complete queueing notice ID = ' . $notice->id . ' for ' . $transport); } return $result; }
/** * Free our claimed queue item for later reprocessing in case of * temporary failure. * * @param QueueItem $qi */ protected function _fail(Queue_item $qi, $releaseOnly = false) { if (empty($qi->claimed)) { $this->_log(LOG_WARNING, "[{$qi->transport}:item {$qi->id}] Ignoring failure for unclaimed queue item"); } else { $qi->releaseClaim(); } if (!$releaseOnly) { $this->stats('error', $qi->transport); } }
function _fail($object, $queue) { // XXX: right now, we only handle notices $notice = $object; $qi = Queue_item::pkeyGet(array('notice_id' => $notice->id, 'transport' => $queue)); if (empty($qi)) { $this->_log(LOG_INFO, 'Cannot find queue item for notice ' . $notice->id . ', queue ' . $queue); } else { if (empty($qi->claimed)) { $this->_log(LOG_WARNING, 'Ignoring failure for unclaimed queue item ' . 'for ' . $notice->id . ', queue ' . $queue); } else { $orig = clone $qi; $qi->claimed = null; $qi->update($orig); $qi = null; } } $this->_log(LOG_INFO, 'done with notice ID = ' . $notice->id); $notice->free(); $notice = null; }
function clear_old_claims() { $qi = new Queue_item(); $qi->transport = $this->transport(); $qi->whereAdd('now() - claimed > ' . CLAIM_TIMEOUT); $qi->update(DB_DATAOBJECT_WHEREADD_ONLY); $qi->free(); unset($qi); }