diff --git a/resources/sql/patches/20130403.conpherencecache.sql b/resources/sql/patches/20130403.conpherencecache.sql new file mode 100644 index 0000000000..830e294fc5 --- /dev/null +++ b/resources/sql/patches/20130403.conpherencecache.sql @@ -0,0 +1,6 @@ +ALTER TABLE {$NAMESPACE}_conpherence.conpherence_thread + ADD recentParticipantPHIDs LONGTEXT NOT NULL COLLATE utf8_bin AFTER title, + ADD messageCount BIGINT UNSIGNED NOT NULL AFTER title; + +ALTER TABLE {$NAMESPACE}_conpherence.conpherence_participant + ADD seenMessageCount BIGINT UNSIGNED NOT NULL AFTER behindTransactionPHID; diff --git a/resources/sql/patches/20130403.conpherencecachemig.php b/resources/sql/patches/20130403.conpherencecachemig.php new file mode 100644 index 0000000000..ffc50006c0 --- /dev/null +++ b/resources/sql/patches/20130403.conpherencecachemig.php @@ -0,0 +1,64 @@ +openTransaction(); +$conn_w = $table->establishConnection('w'); + +$participant_table = new ConpherenceParticipant(); + +$conpherences = new LiskMigrationIterator($table); +foreach ($conpherences as $conpherence) { + echo 'Migrating conpherence #'.$conpherence->getID()."\n"; + + $participants = id(new ConpherenceParticipant()) + ->loadAllWhere('conpherencePHID = %s', $conpherence->getPHID()); + + $transactions = id(new ConpherenceTransaction()) + ->loadAllWhere('objectPHID = %s', $conpherence->getPHID()); + + $participation_hash = mgroup($participants, 'getBehindTransactionPHID'); + + $message_count = 0; + $participants_to_cache = array(); + foreach ($transactions as $transaction) { + $participants_to_cache[] = $transaction->getAuthorPHID(); + if ($transaction->getTransactionType() == + PhabricatorTransactions::TYPE_COMMENT) { + $message_count++; + } + $participants_to_update = idx( + $participation_hash, + $transaction->getPHID(), + array()); + if ($participants_to_update) { + queryfx( + $conn_w, + 'UPDATE %T SET seenMessageCount = %d '. + 'WHERE conpherencePHID = %s AND participantPHID IN (%Ls)', + $participant_table->getTableName(), + $message_count, + $conpherence->getPHID(), + mpull($participants_to_update, 'getParticipantPHID')); + } + } + + $participants_to_cache = array_slice( + array_unique(array_reverse($participants_to_cache)), + 0, + 10); + queryfx( + $conn_w, + 'UPDATE %T '. + 'SET recentParticipantPHIDs = %s, '. + 'messageCount = %d '. + 'WHERE phid = %s', + $table->getTableName(), + json_encode($participants_to_cache), + $message_count, + $conpherence->getPHID()); +} + +$table->saveTransaction(); +echo "\nDone.\n"; diff --git a/src/applications/conpherence/controller/ConpherenceNewController.php b/src/applications/conpherence/controller/ConpherenceNewController.php index 7cfaaae543..6a54b90956 100644 --- a/src/applications/conpherence/controller/ConpherenceNewController.php +++ b/src/applications/conpherence/controller/ConpherenceNewController.php @@ -11,7 +11,8 @@ final class ConpherenceNewController extends ConpherenceController { $conpherence = id(new ConpherenceThread()) ->attachParticipants(array()) - ->attachFilePHIDs(array()); + ->attachFilePHIDs(array()) + ->setMessageCount(0); $title = pht('New Conversation'); $participants = array(); $message = ''; @@ -34,6 +35,8 @@ final class ConpherenceNewController extends ConpherenceController { } else { $participants[] = $user->getPHID(); $participants = array_unique($participants); + $conpherence->setRecentParticipantPHIDs( + array_slice($participants, 0, 10)); } $message = $request->getStr('message'); diff --git a/src/applications/conpherence/controller/ConpherenceViewController.php b/src/applications/conpherence/controller/ConpherenceViewController.php index 8c71c22c15..f4532fe214 100644 --- a/src/applications/conpherence/controller/ConpherenceViewController.php +++ b/src/applications/conpherence/controller/ConpherenceViewController.php @@ -49,7 +49,7 @@ final class ConpherenceViewController extends $transactions = $conpherence->getTransactions(); $latest_transaction = end($transactions); $write_guard = AphrontWriteGuard::beginScopedUnguardedWrites(); - $participant->markUpToDate($latest_transaction); + $participant->markUpToDate($conpherence, $latest_transaction); unset($write_guard); $header = $this->renderHeaderPaneContent(); diff --git a/src/applications/conpherence/editor/ConpherenceEditor.php b/src/applications/conpherence/editor/ConpherenceEditor.php index 50df899217..d7a8ee1260 100644 --- a/src/applications/conpherence/editor/ConpherenceEditor.php +++ b/src/applications/conpherence/editor/ConpherenceEditor.php @@ -86,11 +86,32 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { } } - protected function applyCustomInternalTransaction( + /** + * We really only need a read lock if we have a comment. In that case, we + * must update the messagesCount field on the conpherence and + * seenMessagesCount(s) for the participant(s). + */ + protected function shouldReadLock( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { + $lock = false; switch ($xaction->getTransactionType()) { + case PhabricatorTransactions::TYPE_COMMENT: + $lock = true; + break; + } + + return $lock; + } + + protected function applyCustomInternalTransaction( + PhabricatorLiskDAO $object, + PhabricatorApplicationTransaction $xaction) { + switch ($xaction->getTransactionType()) { + case PhabricatorTransactions::TYPE_COMMENT: + $object->setMessageCount((int)$object->getMessageCount() + 1); + break; case ConpherenceTransactionType::TYPE_TITLE: $object->setTitle($xaction->getNewValue()); break; @@ -105,6 +126,18 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { ConpherenceImageData::SIZE_HEAD); break; } + $this->updateRecentParticipantPHIDs($object, $xaction); + } + + private function updateRecentParticipantPHIDs( + PhabricatorLiskDAO $object, + PhabricatorApplicationTransaction $xaction) { + + $participants = $object->getRecentParticipantPHIDs(); + array_unshift($participants, $xaction->getAuthorPHID()); + $participants = array_slice(array_unique($participants), 0, 10); + + $object->setRecentParticipantPHIDs($participants); } /** @@ -148,10 +181,13 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { if ($phid != $user->getPHID()) { if ($participant->getParticipationStatus() != $behind) { $participant->setBehindTransactionPHID($xaction_phid); + // decrement one as this is the message putting them behind! + $participant->setSeenMessageCount($object->getMessageCount() - 1); } $participant->setParticipationStatus($behind); $participant->setDateTouched($time); } else { + $participant->setSeenMessageCount($object->getMessageCount()); $participant->setParticipationStatus($up_to_date); $participant->setDateTouched($time); } @@ -176,8 +212,10 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { foreach ($add as $phid) { if ($phid == $this->getActor()->getPHID()) { $status = ConpherenceParticipationStatus::UP_TO_DATE; + $message_count = $object->getMessageCount(); } else { $status = ConpherenceParticipationStatus::BEHIND; + $message_count = 0; } $participants[$phid] = id(new ConpherenceParticipant()) @@ -186,6 +224,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { ->setParticipationStatus($status) ->setDateTouched(time()) ->setBehindTransactionPHID($xaction->getPHID()) + ->setSeenMessageCount($message_count) ->save(); } $object->attachParticipants($participants); diff --git a/src/applications/conpherence/storage/ConpherenceParticipant.php b/src/applications/conpherence/storage/ConpherenceParticipant.php index 075a00502f..1dd78130f7 100644 --- a/src/applications/conpherence/storage/ConpherenceParticipant.php +++ b/src/applications/conpherence/storage/ConpherenceParticipant.php @@ -9,6 +9,7 @@ final class ConpherenceParticipant extends ConpherenceDAO { protected $conpherencePHID; protected $participationStatus; protected $behindTransactionPHID; + protected $seenMessageCount; protected $dateTouched; protected $settings = array(); @@ -24,10 +25,13 @@ final class ConpherenceParticipant extends ConpherenceDAO { return nonempty($this->settings, array()); } - public function markUpToDate(ConpherenceTransaction $xaction) { + public function markUpToDate( + ConpherenceThread $conpherence, + ConpherenceTransaction $xaction) { if (!$this->isUpToDate()) { $this->setParticipationStatus(ConpherenceParticipationStatus::UP_TO_DATE); $this->setBehindTransactionPHID($xaction->getPHID()); + $this->setSeenMessageCount($conpherence->getMessageCount()); $this->save(); } return $this; diff --git a/src/applications/conpherence/storage/ConpherenceThread.php b/src/applications/conpherence/storage/ConpherenceThread.php index b9556f6afb..55932f7948 100644 --- a/src/applications/conpherence/storage/ConpherenceThread.php +++ b/src/applications/conpherence/storage/ConpherenceThread.php @@ -9,6 +9,8 @@ final class ConpherenceThread extends ConpherenceDAO protected $id; protected $phid; protected $title; + protected $messageCount; + protected $recentParticipantPHIDs = array(); protected $imagePHIDs = array(); protected $mailKey; @@ -23,7 +25,8 @@ final class ConpherenceThread extends ConpherenceDAO return array( self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( - 'imagePHIDs' => self::SERIALIZATION_JSON, + 'recentParticipantPHIDs' => self::SERIALIZATION_JSON, + 'imagePHIDs' => self::SERIALIZATION_JSON, ), ) + parent::getConfiguration(); } diff --git a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php index 1e06df211f..2a52d0aecd 100644 --- a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php +++ b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php @@ -1226,7 +1226,14 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList { 'type' => 'sql', 'name' => $this->getPatchPath('20130330.phrequent.sql'), ), + '20130403.conpherencecache.sql' => array( + 'type' => 'sql', + 'name' => $this->getPatchPath('20130403.conpherencecache.sql'), + ), + '20130403.conpherencecachemig.php' => array( + 'type' => 'php', + 'name' => $this->getPatchPath('20130403.conpherencecachemig.php'), + ) ); } - }