break up big inbox queries into lots of small ones

This commit is contained in:
Evan Prodromou 2009-06-25 23:00:46 -07:00
parent b53b6b8769
commit 994768b821
6 changed files with 160 additions and 75 deletions

View File

@ -14,8 +14,14 @@ class Group_inbox extends Memcached_DataObject
public $created; // datetime() not_null
/* Static get */
function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Group_inbox',$k,$v); }
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
function &pkeyGet($kv)
{
return Memcached_DataObject::pkeyGet('Group_inbox', $kv);
}
}

View File

@ -832,24 +832,60 @@ class Notice extends Memcached_DataObject
$enabled = common_config('inboxes', 'enabled');
if ($enabled === true || $enabled === 'transitional') {
$inbox = new Notice_inbox();
$UT = common_config('db','type')=='pgsql'?'"user"':'user';
$qry = 'INSERT INTO notice_inbox (user_id, notice_id, created) ' .
"SELECT $UT.id, " . $this->id . ", '" . $this->created . "' " .
"FROM $UT JOIN subscription ON $UT.id = subscription.subscriber " .
'WHERE subscription.subscribed = ' . $this->profile_id . ' ' .
'AND NOT EXISTS (SELECT user_id, notice_id ' .
'FROM notice_inbox ' .
"WHERE user_id = $UT.id " .
'AND notice_id = ' . $this->id . ' )';
if ($enabled === 'transitional') {
$qry .= " AND $UT.inboxed = 1";
$users = $this->getSubscribedUsers();
// FIXME: kind of ignoring 'transitional'...
// we'll probably stop supporting inboxless mode
// in 0.9.x
foreach ($users as $id) {
$this->addToUserInbox($id, NOTICE_INBOX_SOURCE_SUB);
}
$inbox->query($qry);
}
return;
}
function getSubscribedUsers()
{
$user = new User();
$qry =
'SELECT id ' .
'FROM user JOIN subscription '.
'ON user.id = subscription.subscriber ' .
'WHERE subscription.subscribed = %d ';
$user->query(sprintf($qry, $this->profile_id));
$ids = array();
while ($user->fetch()) {
$ids[] = $user->id;
}
$user->free();
return $ids;
}
function addToUserInbox($user_id, $source)
{
$inbox = Notice_inbox::pkeyGet(array('user_id' => $user_id,
'notice_id' => $this->id));
if (empty($inbox)) {
$inbox = new Notice_inbox();
$inbox->user_id = $user_id;
$inbox->notice_id = $this->id;
$inbox->source = $source;
$inbox->created = $this->created;
return $inbox->insert();
}
return true;
}
function saveGroups()
{
$enabled = common_config('inboxes', 'enabled');
@ -888,13 +924,7 @@ class Notice extends Memcached_DataObject
if ($profile->isMember($group)) {
$gi = new Group_inbox();
$gi->group_id = $group->id;
$gi->notice_id = $this->id;
$gi->created = common_sql_now();
$result = $gi->insert();
$result = $this->addToGroupInbox($group);
if (!$result) {
common_log_db_error($gi, 'INSERT', __FILE__);
@ -902,27 +932,37 @@ class Notice extends Memcached_DataObject
// FIXME: do this in an offline daemon
$this->addToGroupInboxes($group);
$this->addToGroupMemberInboxes($group);
}
}
}
function addToGroupInboxes($group)
function addToGroupInbox($group)
{
$inbox = new Notice_inbox();
$UT = common_config('db','type')=='pgsql'?'"user"':'user';
$qry = 'INSERT INTO notice_inbox (user_id, notice_id, created, source) ' .
"SELECT $UT.id, " . $this->id . ", '" . $this->created . "', " . NOTICE_INBOX_SOURCE_GROUP . " " .
"FROM $UT JOIN group_member ON $UT.id = group_member.profile_id " .
'WHERE group_member.group_id = ' . $group->id . ' ' .
'AND NOT EXISTS (SELECT user_id, notice_id ' .
'FROM notice_inbox ' .
"WHERE user_id = $UT.id " .
'AND notice_id = ' . $this->id . ' )';
if ($enabled === 'transitional') {
$qry .= " AND $UT.inboxed = 1";
$gi = Group_inbox::pkeyGet(array('group_id' => $group->id,
'notice_id' => $this->id));
if (empty($gi)) {
$gi = new Group_inbox();
$gi->group_id = $group->id;
$gi->notice_id = $this->id;
$gi->created = $this->created;
return $gi->insert();
}
return true;
}
function addToGroupMemberInboxes($group)
{
$users = $group->getUserMembers();
foreach ($users as $id) {
$this->addToUserInbox($id, NOTICE_INBOX_SOURCE_GROUP);
}
$result = $inbox->query($qry);
}
function saveReplies()

View File

@ -27,6 +27,7 @@ define('INBOX_CACHE_WINDOW', 101);
define('NOTICE_INBOX_SOURCE_SUB', 1);
define('NOTICE_INBOX_SOURCE_GROUP', 2);
define('NOTICE_INBOX_SOURCE_REPLY', 3);
define('NOTICE_INBOX_SOURCE_GATEWAY', -1);
class Notice_inbox extends Memcached_DataObject

View File

@ -289,4 +289,52 @@ class Profile extends Memcached_DataObject
return Avatar::defaultImage($size);
}
}
function getSubscriptions($offset=0, $limit=null)
{
$qry =
'SELECT profile.* ' .
'FROM profile JOIN subscription ' .
'ON profile.id = subscription.subscribed ' .
'WHERE subscription.subscriber = %d ' .
'AND subscription.subscribed != subscription.subscriber ' .
'ORDER BY subscription.created DESC ';
if (common_config('db','type') == 'pgsql') {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
}
$profile = new Profile();
$profile->query(sprintf($qry, $this->id));
return $profile;
}
function getSubscribers($offset=0, $limit=null)
{
$qry =
'SELECT profile.* ' .
'FROM profile JOIN subscription ' .
'ON profile.id = subscription.subscriber ' .
'WHERE subscription.subscribed = %d ' .
'AND subscription.subscribed != subscription.subscriber ' .
'ORDER BY subscription.created DESC ';
if ($offset) {
if (common_config('db','type') == 'pgsql') {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
}
}
$profile = new Profile();
$cnt = $profile->query(sprintf($qry, $this->id));
return $profile;
}
}

View File

@ -600,50 +600,16 @@ class User extends Memcached_DataObject
function getSubscriptions($offset=0, $limit=null)
{
$qry =
'SELECT profile.* ' .
'FROM profile JOIN subscription ' .
'ON profile.id = subscription.subscribed ' .
'WHERE subscription.subscriber = %d ' .
'AND subscription.subscribed != subscription.subscriber ' .
'ORDER BY subscription.created DESC ';
if (common_config('db','type') == 'pgsql') {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
}
$profile = new Profile();
$profile->query(sprintf($qry, $this->id));
return $profile;
$profile = $this->getProfile();
assert(!empty($profile));
return $profile->getSubscriptions($offset, $limit);
}
function getSubscribers($offset=0, $limit=null)
{
$qry =
'SELECT profile.* ' .
'FROM profile JOIN subscription ' .
'ON profile.id = subscription.subscriber ' .
'WHERE subscription.subscribed = %d ' .
'AND subscription.subscribed != subscription.subscriber ' .
'ORDER BY subscription.created DESC ';
if ($offset) {
if (common_config('db','type') == 'pgsql') {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
}
}
$profile = new Profile();
$cnt = $profile->query(sprintf($qry, $this->id));
return $profile;
$profile = $this->getProfile();
assert(!empty($profile));
return $profile->getSubscribers($offset, $limit);
}
function getTaggedSubscribers($tag, $offset=0, $limit=null)

View File

@ -246,4 +246,28 @@ class User_group extends Memcached_DataObject
return Design::staticGet('id', $this->design_id);
}
function getUserMembers()
{
// XXX: cache this
$user = new User();
$qry =
'SELECT id ' .
'FROM user JOIN group_member '.
'ON user.id = group_member.profile_id ' .
'WHERE group_member.group_id = %d ';
$user->query(sprintf($qry, $this->id));
$ids = array();
while ($user->fetch()) {
$ids[] = $user->id;
}
$user->free();
return $ids;
}
}