Page MenuHomePhabricator

D16041.id38608.diff
No OneTemporary

D16041.id38608.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -3640,6 +3640,8 @@
'PhabricatorUserIconField' => 'applications/people/customfield/PhabricatorUserIconField.php',
'PhabricatorUserLog' => 'applications/people/storage/PhabricatorUserLog.php',
'PhabricatorUserLogView' => 'applications/people/view/PhabricatorUserLogView.php',
+ 'PhabricatorUserMessageCountCacheType' => 'applications/people/cache/PhabricatorUserMessageCountCacheType.php',
+ 'PhabricatorUserNotificationCountCacheType' => 'applications/people/cache/PhabricatorUserNotificationCountCacheType.php',
'PhabricatorUserPHIDResolver' => 'applications/phid/resolver/PhabricatorUserPHIDResolver.php',
'PhabricatorUserPreferences' => 'applications/settings/storage/PhabricatorUserPreferences.php',
'PhabricatorUserPreferencesCacheType' => 'applications/people/cache/PhabricatorUserPreferencesCacheType.php',
@@ -8451,6 +8453,8 @@
'PhabricatorPolicyInterface',
),
'PhabricatorUserLogView' => 'AphrontView',
+ 'PhabricatorUserMessageCountCacheType' => 'PhabricatorUserCacheType',
+ 'PhabricatorUserNotificationCountCacheType' => 'PhabricatorUserCacheType',
'PhabricatorUserPHIDResolver' => 'PhabricatorPHIDResolver',
'PhabricatorUserPreferences' => array(
'PhabricatorUserDAO',
diff --git a/src/applications/aphlict/query/AphlictDropdownDataQuery.php b/src/applications/aphlict/query/AphlictDropdownDataQuery.php
--- a/src/applications/aphlict/query/AphlictDropdownDataQuery.php
+++ b/src/applications/aphlict/query/AphlictDropdownDataQuery.php
@@ -46,17 +46,15 @@
$is_c_installed = PhabricatorApplication::isClassInstalledForViewer(
$conpherence_app,
$viewer);
- $raw_message_count_number = null;
- $message_count_number = null;
if ($is_c_installed) {
- $unread_status = ConpherenceParticipationStatus::BEHIND;
- $unread = id(new ConpherenceParticipantCountQuery())
- ->withParticipantPHIDs(array($viewer->getPHID()))
- ->withParticipationStatus($unread_status)
- ->execute();
- $raw_message_count_number = idx($unread, $viewer->getPHID(), 0);
+ $raw_message_count_number = $viewer->getUnreadMessageCount();
$message_count_number = $this->formatNumber($raw_message_count_number);
+ } else {
+ $raw_message_count_number = null;
+ $message_count_number = null;
}
+
+
$conpherence_data = array(
'isInstalled' => $is_c_installed,
'countType' => 'messages',
@@ -69,15 +67,15 @@
$is_n_installed = PhabricatorApplication::isClassInstalledForViewer(
$notification_app,
$viewer);
- $notification_count_number = null;
- $raw_notification_count_number = null;
if ($is_n_installed) {
- $raw_notification_count_number =
- id(new PhabricatorFeedStoryNotification())
- ->countUnread($viewer);
+ $raw_notification_count_number = $viewer->getUnreadNotificationCount();
$notification_count_number = $this->formatNumber(
$raw_notification_count_number);
+ } else {
+ $notification_count_number = null;
+ $raw_notification_count_number = null;
}
+
$notification_data = array(
'isInstalled' => $is_n_installed,
'countType' => 'notifications',
diff --git a/src/applications/conpherence/controller/ConpherenceViewController.php b/src/applications/conpherence/controller/ConpherenceViewController.php
--- a/src/applications/conpherence/controller/ConpherenceViewController.php
+++ b/src/applications/conpherence/controller/ConpherenceViewController.php
@@ -68,9 +68,12 @@
$latest_transaction = head($transactions);
$participant = $conpherence->getParticipantIfExists($user->getPHID());
if ($participant) {
- $write_guard = AphrontWriteGuard::beginScopedUnguardedWrites();
- $participant->markUpToDate($conpherence, $latest_transaction);
- unset($write_guard);
+ if (!$participant->isUpToDate($conpherence)) {
+ $write_guard = AphrontWriteGuard::beginScopedUnguardedWrites();
+ $participant->markUpToDate($conpherence, $latest_transaction);
+ $user->clearCacheData(PhabricatorUserMessageCountCacheType::KEY_COUNT);
+ unset($write_guard);
+ }
}
$data = ConpherenceTransactionRenderer::renderTransactions(
diff --git a/src/applications/conpherence/editor/ConpherenceEditor.php b/src/applications/conpherence/editor/ConpherenceEditor.php
--- a/src/applications/conpherence/editor/ConpherenceEditor.php
+++ b/src/applications/conpherence/editor/ConpherenceEditor.php
@@ -422,6 +422,10 @@
$participant->save();
}
+ PhabricatorUserCache::clearCaches(
+ PhabricatorUserMessageCountCacheType::KEY_COUNT,
+ array_keys($participants));
+
if ($xactions) {
$data = array(
'type' => 'message',
diff --git a/src/applications/conpherence/storage/ConpherenceParticipant.php b/src/applications/conpherence/storage/ConpherenceParticipant.php
--- a/src/applications/conpherence/storage/ConpherenceParticipant.php
+++ b/src/applications/conpherence/storage/ConpherenceParticipant.php
@@ -47,11 +47,16 @@
$this->setBehindTransactionPHID($xaction->getPHID());
$this->setSeenMessageCount($conpherence->getMessageCount());
$this->save();
+
+ PhabricatorUserCache::clearCache(
+ PhabricatorUserMessageCountCacheType::KEY_COUNT,
+ $this->getParticipantPHID());
}
+
return $this;
}
- private function isUpToDate(ConpherenceThread $conpherence) {
+ public function isUpToDate(ConpherenceThread $conpherence) {
return
($this->getSeenMessageCount() == $conpherence->getMessageCount())
&&
diff --git a/src/applications/feed/PhabricatorFeedStoryPublisher.php b/src/applications/feed/PhabricatorFeedStoryPublisher.php
--- a/src/applications/feed/PhabricatorFeedStoryPublisher.php
+++ b/src/applications/feed/PhabricatorFeedStoryPublisher.php
@@ -159,7 +159,8 @@
$will_receive_mail = array_fill_keys($this->mailRecipientPHIDs, true);
- foreach (array_unique($subscribed_phids) as $user_phid) {
+ $user_phids = array_unique($subscribed_phids);
+ foreach ($user_phids as $user_phid) {
if (isset($will_receive_mail[$user_phid])) {
$mark_read = 1;
} else {
@@ -184,6 +185,10 @@
$notif->getTableName(),
implode(', ', $sql));
}
+
+ PhabricatorUserCache::clearCaches(
+ PhabricatorUserNotificationCountCacheType::KEY_COUNT,
+ $user_phids);
}
private function sendNotification($chrono_key, array $subscribed_phids) {
diff --git a/src/applications/files/query/PhabricatorFileQuery.php b/src/applications/files/query/PhabricatorFileQuery.php
--- a/src/applications/files/query/PhabricatorFileQuery.php
+++ b/src/applications/files/query/PhabricatorFileQuery.php
@@ -134,6 +134,9 @@
return $files;
}
+ $viewer = $this->getViewer();
+ $is_omnipotent = $viewer->isOmnipotent();
+
// We need to load attached objects to perform policy checks for files.
// First, load the edges.
@@ -156,6 +159,13 @@
continue;
}
+ if ($is_omnipotent) {
+ // If the viewer is omnipotent, we don't need to load the associated
+ // objects either since they can certainly see the object. Skipping
+ // this can improve performance and prevent cycles.
+ continue;
+ }
+
foreach ($phids as $phid) {
$object_phids[$phid] = true;
}
diff --git a/src/applications/notification/controller/PhabricatorNotificationClearController.php b/src/applications/notification/controller/PhabricatorNotificationClearController.php
--- a/src/applications/notification/controller/PhabricatorNotificationClearController.php
+++ b/src/applications/notification/controller/PhabricatorNotificationClearController.php
@@ -18,6 +18,10 @@
$viewer->getPHID(),
$chrono_key);
+ PhabricatorUserCache::clearCache(
+ PhabricatorUserNotificationCountCacheType::KEY_COUNT,
+ $viewer->getPHID());
+
return id(new AphrontReloadResponse())
->setURI('/notification/');
}
diff --git a/src/applications/notification/controller/PhabricatorNotificationPanelController.php b/src/applications/notification/controller/PhabricatorNotificationPanelController.php
--- a/src/applications/notification/controller/PhabricatorNotificationPanelController.php
+++ b/src/applications/notification/controller/PhabricatorNotificationPanelController.php
@@ -71,8 +71,7 @@
$content,
$connection_ui);
- $unread_count = id(new PhabricatorFeedStoryNotification())
- ->countUnread($viewer);
+ $unread_count = $viewer->getUnreadNotificationCount();
$json = array(
'content' => $content,
diff --git a/src/applications/notification/storage/PhabricatorFeedStoryNotification.php b/src/applications/notification/storage/PhabricatorFeedStoryNotification.php
--- a/src/applications/notification/storage/PhabricatorFeedStoryNotification.php
+++ b/src/applications/notification/storage/PhabricatorFeedStoryNotification.php
@@ -60,20 +60,10 @@
$object_phid);
unset($unguarded);
- }
-
- public function countUnread(PhabricatorUser $user) {
- $conn = $this->establishConnection('r');
-
- $data = queryfx_one(
- $conn,
- 'SELECT COUNT(*) as count
- FROM %T
- WHERE userPHID = %s AND hasViewed = 0',
- $this->getTableName(),
- $user->getPHID());
- return $data['count'];
+ $count_key = PhabricatorUserNotificationCountCacheType::KEY_COUNT;
+ PhabricatorUserCache::clearCache($count_key, $user->getPHID());
+ $user->clearCacheData($count_key);
}
}
diff --git a/src/applications/people/cache/PhabricatorUserMessageCountCacheType.php b/src/applications/people/cache/PhabricatorUserMessageCountCacheType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/people/cache/PhabricatorUserMessageCountCacheType.php
@@ -0,0 +1,45 @@
+<?php
+
+final class PhabricatorUserMessageCountCacheType
+ extends PhabricatorUserCacheType {
+
+ const CACHETYPE = 'message.count';
+
+ const KEY_COUNT = 'user.message.count.v1';
+
+ public function getAutoloadKeys() {
+ return array(
+ self::KEY_COUNT,
+ );
+ }
+
+ public function canManageKey($key) {
+ return ($key === self::KEY_COUNT);
+ }
+
+ public function getValueFromStorage($value) {
+ return (int)$value;
+ }
+
+ public function getValueForStorage($value) {
+ return $value;
+ }
+
+ public function newValueForUsers($key, array $users) {
+ if (!$users) {
+ return array();
+ }
+
+ $user_phids = mpull($users, 'getPHID');
+
+ $unread_status = ConpherenceParticipationStatus::BEHIND;
+ $unread = id(new ConpherenceParticipantCountQuery())
+ ->withParticipantPHIDs($user_phids)
+ ->withParticipationStatus($unread_status)
+ ->execute();
+
+ $empty = array_fill_keys($user_phids, 0);
+ return $unread + $empty;
+ }
+
+}
diff --git a/src/applications/people/cache/PhabricatorUserNotificationCountCacheType.php b/src/applications/people/cache/PhabricatorUserNotificationCountCacheType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/people/cache/PhabricatorUserNotificationCountCacheType.php
@@ -0,0 +1,50 @@
+<?php
+
+final class PhabricatorUserNotificationCountCacheType
+ extends PhabricatorUserCacheType {
+
+ const CACHETYPE = 'notification.count';
+
+ const KEY_COUNT = 'user.notification.count.v1';
+
+ public function getAutoloadKeys() {
+ return array(
+ self::KEY_COUNT,
+ );
+ }
+
+ public function canManageKey($key) {
+ return ($key === self::KEY_COUNT);
+ }
+
+ public function getValueFromStorage($value) {
+ return (int)$value;
+ }
+
+ public function getValueForStorage($value) {
+ return $value;
+ }
+
+ public function newValueForUsers($key, array $users) {
+ if (!$users) {
+ return array();
+ }
+
+ $user_phids = mpull($users, 'getPHID');
+
+ $table = new PhabricatorFeedStoryNotification();
+ $conn_r = $table->establishConnection('r');
+
+ $rows = queryfx_all(
+ $conn_r,
+ 'SELECT userPHID, COUNT(*) N FROM %T
+ WHERE userPHID IN (%Ls) AND hasViewed = 0
+ GROUP BY userPHID',
+ $table->getTableName(),
+ $user_phids);
+
+ $empty = array_fill_keys($user_phids, 0);
+ return ipull($rows, 'N', 'userPHID') + $empty;
+ }
+
+}
diff --git a/src/applications/people/storage/PhabricatorUser.php b/src/applications/people/storage/PhabricatorUser.php
--- a/src/applications/people/storage/PhabricatorUser.php
+++ b/src/applications/people/storage/PhabricatorUser.php
@@ -792,6 +792,16 @@
return $this->requireCacheData($uri_key);
}
+ public function getUnreadNotificationCount() {
+ $notification_key = PhabricatorUserNotificationCountCacheType::KEY_COUNT;
+ return $this->requireCacheData($notification_key);
+ }
+
+ public function getUnreadMessageCount() {
+ $message_key = PhabricatorUserMessageCountCacheType::KEY_COUNT;
+ return $this->requireCacheData($message_key);
+ }
+
public function getFullName() {
if (strlen($this->getRealName())) {
return $this->getUsername().' ('.$this->getRealName().')';
diff --git a/src/applications/people/storage/PhabricatorUserCache.php b/src/applications/people/storage/PhabricatorUserCache.php
--- a/src/applications/people/storage/PhabricatorUserCache.php
+++ b/src/applications/people/storage/PhabricatorUserCache.php
@@ -97,10 +97,18 @@
}
public static function clearCache($key, $user_phid) {
+ return self::clearCaches($key, array($user_phid));
+ }
+
+ public static function clearCaches($key, array $user_phids) {
if (PhabricatorEnv::isReadOnly()) {
return;
}
+ if (!$user_phids) {
+ return;
+ }
+
$table = new self();
$conn_w = $table->establishConnection('w');
@@ -108,15 +116,14 @@
queryfx(
$conn_w,
- 'DELETE FROM %T WHERE cacheIndex = %s AND userPHID = %s',
+ 'DELETE FROM %T WHERE cacheIndex = %s AND userPHID IN (%Ls)',
$table->getTableName(),
PhabricatorHash::digestForIndex($key),
- $user_phid);
+ $user_phids);
unset($unguarded);
}
-
public static function clearCacheForAllUsers($key) {
if (PhabricatorEnv::isReadOnly()) {
return;
diff --git a/src/applications/settings/editor/PhabricatorUserPreferencesEditor.php b/src/applications/settings/editor/PhabricatorUserPreferencesEditor.php
--- a/src/applications/settings/editor/PhabricatorUserPreferencesEditor.php
+++ b/src/applications/settings/editor/PhabricatorUserPreferencesEditor.php
@@ -162,7 +162,6 @@
PhabricatorUserPreferencesCacheType::KEY_PREFERENCES);
}
-
return $xactions;
}
diff --git a/src/applications/transactions/worker/PhabricatorApplicationTransactionPublishWorker.php b/src/applications/transactions/worker/PhabricatorApplicationTransactionPublishWorker.php
--- a/src/applications/transactions/worker/PhabricatorApplicationTransactionPublishWorker.php
+++ b/src/applications/transactions/worker/PhabricatorApplicationTransactionPublishWorker.php
@@ -84,8 +84,10 @@
$xaction_phids = idx($data, 'xactionPHIDs');
if (!$xaction_phids) {
- throw new PhabricatorWorkerPermanentFailureException(
- pht('Task has no transaction PHIDs!'));
+ // It's okay if we don't have any transactions. This can happen when
+ // creating objects or performing no-op updates. We will still apply
+ // meaningful side effects like updating search engine indexes.
+ return array();
}
$viewer = PhabricatorUser::getOmnipotentUser();

File Metadata

Mime Type
text/plain
Expires
Fri, Dec 20, 10:22 AM (57 m, 55 s)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6909404
Default Alt Text
D16041.id38608.diff (15 KB)

Event Timeline