From 73a0271960a5e7e2bc6e040595d3071d7b689a99 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 4 Jul 2008 01:04:25 -0400 Subject: [PATCH] enqueue notices for offline broadcast darcs-hash:20080704050425-84dde-d0106845c7b16b80be8e0d5ee9ac93a457334df7.gz --- config.php.sample | 4 ++ lib/common.php | 2 + lib/util.php | 21 +++++++++- queuedaemon.php | 102 ++++++++++++++++++++++++++++++++++++++++++++++ xmppdaemon.php | 2 + 5 files changed, 130 insertions(+), 1 deletion(-) create mode 100755 queuedaemon.php diff --git a/config.php.sample b/config.php.sample index add56b8392..2dbdbb673e 100644 --- a/config.php.sample +++ b/config.php.sample @@ -50,3 +50,7 @@ $config['db']['database'] = 'mysql://laconica:microblog@localhost/laconica'; #$config['xmpp']['resource'] = 'uniquename'; #$config['xmpp']['password'] = 'blahblahblah'; +#Do notice broadcasts offline +#If you set this, you must run the queuehandler.php +#as a daemon (with, say, start-stop-daemon) +#$config['queue']['enabled'] = true; \ No newline at end of file diff --git a/lib/common.php b/lib/common.php index 691d339536..0b5b4ab5cc 100644 --- a/lib/common.php +++ b/lib/common.php @@ -51,6 +51,8 @@ $config = array('authority' => 'INVALID TAG', 'date' => 'PUT A DATE HERE', 'prefix' => ''), + 'queue' => + array('enabled' => false), 'license' => array('url' => 'http://creativecommons.org/licenses/by/3.0/', 'title' => 'Creative Commons Attribution 3.0', diff --git a/lib/util.php b/lib/util.php index 4d1abe51a7..03d549334a 100644 --- a/lib/util.php +++ b/lib/util.php @@ -808,6 +808,25 @@ function common_redirect($url, $code=307) { } function common_broadcast_notice($notice, $remote=false) { + if (common_config('queue', 'enabled')) { + # Do it later! + common_enqueue_notice($notice); + } else { + common_real_broadcast($notice, $remote); + } +} + +# Stick the notice on the queue + +function common_enqueue_notice($notice) { + $qi = new Queue_item(); + $qi->notice_id = $notice->id; + $qi->created = DB_DataObject_Cast::dateTime(); + $result = $qi->insert(); + return $result; +} + +function common_real_broadcast($notice, $remote=false) { // XXX: optionally use a queue system like http://code.google.com/p/microapps/wiki/NQDQ if (!$remote) { # Make sure we have the OMB stuff @@ -939,7 +958,7 @@ function common_ensure_syslog() { function common_log($priority, $msg, $filename=NULL) { common_ensure_syslog(); -# syslog($priority, $msg); + syslog($priority, $msg); } function common_debug($msg, $filename=NULL) { diff --git a/queuedaemon.php b/queuedaemon.php new file mode 100755 index 0000000000..9d8a465a6d --- /dev/null +++ b/queuedaemon.php @@ -0,0 +1,102 @@ +#!/usr/bin/env php +. + */ + +# Abort if called from a web server +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { + print "This script must be run from the command line\n"; + exit(); +} + +define('INSTALLDIR', dirname(__FILE__)); +define('LACONICA', true); + +require_once(INSTALLDIR . '/lib/common.php'); + +# Notices should be broadcast in 30 minutes or less + +define('CLAIM_TIMEOUT', 30 * 60); + +function qd_log($priority, $msg) { + common_log($level, 'queuedaemon: '.$msg); +} + +function qd_top_item() { + + $qi = new Queue_item(); + $qi->orderBy('created'); + $qi->whereAdd('claimed is NULL', 'OR'); + $qi->whereAdd('now() - claimed > '.CLAIM_TIMEOUT, 'OR'); + + $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)? + $orig = clone($qi); + $qi->claimed = DB_DataObject_Cast::dateTime(); + $result = $qi->update($orig); + if ($result) { + return $qi; + } + } + $qi = NULL; + return NULL; +} + +function qd_is_remote($notice) { + $user = User::staticGet($notice->profile_id); + return !$user; +} + +$in_a_row = 0; + +do { + qd_log(LOG_INFO, 'checking for queued notices'); + $qi = qd_top_item(); + if ($qi) { + $in_a_row++; + qd_log(LOG_INFO, 'Got queue item #'.$in_a_row.' enqueued '.common_exact_date($qi->created)); + $notice = Notice::staticGet($qi->notice_id); + if ($notice) { + qd_log(LOG_INFO, 'broadcasting notice ID = ' . $notice->id); + # XXX: what to do if broadcast fails? + common_real_broadcast($notice, qd_is_remote($notice)); + qd_log(LOG_INFO, 'finished broadcasting notice ID = ' . $notice->id); + $notice = NULL; + } else { + qd_log(LOG_WARNING, 'queue item for notice that does not exist'); + } + $qi->delete(); + $qi = NULL; + } else { + # In busy times, sleep less + $sleeptime = 30000000/($in_a_row+1); + qd_log(LOG_INFO, 'sleeping ' . $sleeptime . ' microseconds'); + usleep($sleeptime); + $in_a_row = 0; + } + # Clear the DB_DataObject cache so we get fresh data + $GLOBALS['_DB_DATAOBJECT']['CACHE'] = array(); +} while (true); + +?> diff --git a/xmppdaemon.php b/xmppdaemon.php index afe248c8e4..fc9d67d2e5 100755 --- a/xmppdaemon.php +++ b/xmppdaemon.php @@ -85,6 +85,8 @@ class XMPPDaemon { break; } } + # Flush DB_DataObject cache so we get fresh info + $GLOBALS['_DB_DATAOBJECT']['CACHE'] = array(); } }