* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
/**
* PuSH feed subscription record
* @package Hub
* @author Brion Vibber <brion@status.net>
*/
-class HubSub extends Memcached_DataObject
+class HubSub extends Managed_DataObject
{
public $__table = 'hubsub';
public $created;
public $modified;
- public /*static*/ function staticGet($topic, $callback)
- {
- return parent::staticGet(__CLASS__, 'hashkey', self::hashkey($topic, $callback));
- }
-
protected static function hashkey($topic, $callback)
{
return sha1($topic . '|' . $callback);
}
- /**
- * return table definition for DB_DataObject
- *
- * DB_DataObject needs to know something about the table to manipulate
- * instances. This method provides all the DB_DataObject needs to know.
- *
- * @return array array of column definitions
- */
-
- function table()
- {
- return array('hashkey' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
- 'topic' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
- 'callback' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
- 'secret' => DB_DATAOBJECT_STR,
- 'lease' => DB_DATAOBJECT_INT,
- 'sub_start' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME,
- 'sub_end' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME,
- 'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL,
- 'modified' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
- }
-
- static function schemaDef()
- {
- return array(new ColumnDef('hashkey', 'char',
- /*size*/40,
- /*nullable*/false,
- /*key*/'PRI'),
- new ColumnDef('topic', 'varchar',
- /*size*/255,
- /*nullable*/false,
- /*key*/'MUL'),
- new ColumnDef('callback', 'varchar',
- 255, false),
- new ColumnDef('secret', 'text',
- null, true),
- new ColumnDef('lease', 'int',
- null, true),
- new ColumnDef('sub_start', 'datetime',
- null, true),
- new ColumnDef('sub_end', 'datetime',
- null, true),
- new ColumnDef('created', 'datetime',
- null, false),
- new ColumnDef('modified', 'datetime',
- null, false));
- }
-
- function keys()
- {
- return array_keys($this->keyTypes());
- }
-
- function sequenceKey()
+ public static function getByHashkey($topic, $callback)
{
- return array(false, false, false);
+ return self::getKV('hashkey', self::hashkey($topic, $callback));
}
- /**
- * return key definitions for DB_DataObject
- *
- * DB_DataObject needs to know about keys that the table has; this function
- * defines them.
- *
- * @return array key definitions
- */
-
- function keyTypes()
+ public static function schemaDef()
{
- return array('hashkey' => 'K');
+ return array(
+ 'fields' => array(
+ 'hashkey' => array('type' => 'char', 'not null' => true, 'length' => 40, 'description' => 'HubSub hashkey'),
+ 'topic' => array('type' => 'varchar', 'not null' => true, 'length' => 255, 'description' => 'HubSub topic'),
+ 'callback' => array('type' => 'varchar', 'not null' => true, 'length' => 255, 'description' => 'HubSub callback'),
+ 'secret' => array('type' => 'text', 'description' => 'HubSub stored secret'),
+ 'lease' => array('type' => 'int', 'not null' => true, 'description' => 'HubSub leasetime'),
+ 'sub_start' => array('type' => 'datetime', 'description' => 'subscription start'),
+ 'sub_end' => array('type' => 'datetime', 'description' => 'subscription end'),
+ 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
+ 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
+ ),
+ 'primary key' => array('hashkey'),
+ 'indexes' => array(
+ 'hubsub_topic_idx' => array('topic'),
+ ),
+ );
}
/**
if ($status >= 200 && $status < 300) {
common_log(LOG_INFO, "Verified $mode of $this->callback:$this->topic");
} else {
- throw new ClientException("Hub subscriber verification returned HTTP $status");
+ // TRANS: Client exception. %s is a HTTP status code.
+ throw new ClientException(sprintf(_m('Hub subscriber verification returned HTTP %s.'),$status));
}
- $old = HubSub::staticGet($this->topic, $this->callback);
+ $old = HubSub::getByHashkey($this->topic, $this->callback);
if ($mode == 'subscribe') {
if ($old) {
$this->update($old);
// destroy the result data for the parent query.
// @fixme use clone() again when it's safe to copy an
// individual item from a multi-item query again.
- $sub = HubSub::staticGet($this->topic, $this->callback);
+ $sub = HubSub::getByHashkey($this->topic, $this->callback);
$data = array('sub' => $sub,
'atom' => $atom,
'retries' => $retries);
$qm->enqueue($data, 'hubout');
}
+ /**
+ * Queue up a large batch of pushes to multiple subscribers
+ * for this same topic update.
+ *
+ * If queues are disabled, this will run immediately.
+ *
+ * @param string $atom well-formed Atom feed
+ * @param array $pushCallbacks list of callback URLs
+ */
+ function bulkDistribute($atom, $pushCallbacks)
+ {
+ $data = array('atom' => $atom,
+ 'topic' => $this->topic,
+ 'pushCallbacks' => $pushCallbacks);
+ common_log(LOG_INFO, "Queuing PuSH batch: $this->topic to " .
+ count($pushCallbacks) . " sites");
+ $qm = QueueManager::get();
+ $qm->enqueue($data, 'hubprep');
+ }
+
/**
* Send a 'fat ping' to the subscriber's callback endpoint
* containing the given Atom feed chunk.
if ($response->isOk()) {
return true;
} else {
- throw new Exception("Callback returned status: " .
- $response->getStatus() .
- "; body: " .
- trim($response->getBody()));
+ // TRANS: Exception. %1$s is a response status code, %2$s is the body of the response.
+ throw new Exception(sprintf(_m('Callback returned status: %1$s. Body: %2$s'),
+ $response->getStatus(),trim($response->getBody())));
}
}
}
-