Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13983831
D12838.id30897.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
8 KB
Referenced Files
None
Subscribers
None
D12838.id30897.diff
View Options
diff --git a/resources/sql/autopatches/20150514.user.cache.2.sql b/resources/sql/autopatches/20150514.user.cache.2.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150514.user.cache.2.sql
@@ -0,0 +1,5 @@
+ALTER TABLE {$NAMESPACE}_user.user
+ ADD availabilityCache VARCHAR(255) COLLATE {$COLLATE_TEXT};
+
+ALTER TABLE {$NAMESPACE}_user.user
+ ADD availabilityCacheTTL INT UNSIGNED;
diff --git a/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php b/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
--- a/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
+++ b/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
@@ -55,16 +55,7 @@
case PhabricatorCalendarEventTransaction::TYPE_INVITE:
$map = $xaction->getNewValue();
$phids = array_keys($map);
- $invitees = array();
-
- if ($map && !$this->getIsNewObject()) {
- $invitees = id(new PhabricatorCalendarEventInviteeQuery())
- ->setViewer($this->getActor())
- ->withEventPHIDs(array($object->getPHID()))
- ->withInviteePHIDs($phids)
- ->execute();
- $invitees = mpull($invitees, null, 'getInviteePHID');
- }
+ $invitees = mpull($object->getInvitees(), null, 'getInviteePHID');
$old = array();
foreach ($phids as $phid) {
@@ -193,6 +184,53 @@
return $xactions;
}
+ protected function applyFinalEffects($object, array $xactions) {
+
+ // Clear the availability caches for users whose availability is affected
+ // by this edit.
+
+ $invalidate_all = false;
+ $invalidate_phids = array();
+ foreach ($xactions as $xaction) {
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
+ case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
+ case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
+ case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY:
+ // For these kinds of changes, we need to invalidate the availabilty
+ // caches for all attendees.
+ $invalidate_all = true;
+ break;
+ case PhabricatorCalendarEventTransaction::TYPE_INVITE:
+ foreach ($xaction->getNewValue() as $phid => $ignored) {
+ $invalidate_phids[$phid] = $phid;
+ }
+ break;
+ }
+ }
+
+ $phids = mpull($object->getInvitees(), 'getInviteePHID');
+ $phids = array_fuse($phids);
+
+ if (!$invalidate_all) {
+ $phids = array_select_keys($phids, $invalidate_phids);
+ }
+
+ if ($phids) {
+ $user = new PhabricatorUser();
+ $conn_w = $user->establishConnection('w');
+ queryfx(
+ $conn_w,
+ 'UPDATE %T SET availabilityCacheTTL = NULL
+ WHERE phid IN (%Ls) AND availabilityCacheTTL >= %d',
+ $user->getTableName(),
+ $phids,
+ $object->getDateFromForCache());
+ }
+
+ return $xactions;
+ }
+
protected function validateAllTransactions(
PhabricatorLiskDAO $object,
diff --git a/src/applications/calendar/storage/PhabricatorCalendarEvent.php b/src/applications/calendar/storage/PhabricatorCalendarEvent.php
--- a/src/applications/calendar/storage/PhabricatorCalendarEvent.php
+++ b/src/applications/calendar/storage/PhabricatorCalendarEvent.php
@@ -147,6 +147,19 @@
return parent::save();
}
+ /**
+ * Get the event start epoch for evaluating invitee availability.
+ *
+ * When assessing availability, we pretend events start earlier than they
+ * really. This allows us to mark users away for the entire duration of a
+ * series of back-to-back meetings, even if they don't strictly overlap.
+ *
+ * @return int Event start date for availability caches.
+ */
+ public function getDateFromForCache() {
+ return ($this->getDateFrom() - phutil_units('15 minutes in seconds'));
+ }
+
private static $statusTexts = array(
self::STATUS_AWAY => 'away',
self::STATUS_SPORADIC => 'sporadic',
diff --git a/src/applications/people/query/PhabricatorPeopleQuery.php b/src/applications/people/query/PhabricatorPeopleQuery.php
--- a/src/applications/people/query/PhabricatorPeopleQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleQuery.php
@@ -201,8 +201,16 @@
}
if ($this->needAvailability) {
- // TODO: Add caching.
- $rebuild = $users;
+ $rebuild = array();
+ foreach ($users as $user) {
+ $cache = $user->getAvailabilityCache();
+ if ($cache !== null) {
+ $user->attachAvailability($cache);
+ } else {
+ $rebuild[] = $user;
+ }
+ }
+
if ($rebuild) {
$this->rebuildAvailabilityCache($rebuild);
}
@@ -405,11 +413,6 @@
}
}
- // Margin between meetings: pretend meetings start earlier than they do
- // so we mark you away for the entire time if you have a series of
- // back-to-back meetings, even if they don't strictly overlap.
- $margin = phutil_units('15 minutes in seconds');
-
foreach ($rebuild as $phid => $user) {
$events = idx($map, $phid, array());
@@ -419,7 +422,7 @@
// because of an event, we check again for events after that one ends.
while (true) {
foreach ($events as $event) {
- $from = ($event->getDateFrom() - $margin);
+ $from = $event->getDateFromForCache();
$to = $event->getDateTo();
if (($from <= $cursor) && ($to > $cursor)) {
$cursor = $to;
@@ -436,15 +439,16 @@
);
$availability_ttl = $cursor;
} else {
- $availability = null;
+ $availability = array(
+ 'until' => null,
+ );
$availability_ttl = $max_range;
}
// Never TTL the cache to longer than the maximum range we examined.
$availability_ttl = min($availability_ttl, $max_range);
- // TODO: Write the cache.
-
+ $user->writeAvailabilityCache($availability, $availability_ttl);
$user->attachAvailability($availability);
}
}
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
@@ -27,6 +27,8 @@
protected $passwordHash;
protected $profileImagePHID;
protected $profileImageCache;
+ protected $availabilityCache;
+ protected $availabilityCacheTTL;
protected $timezoneIdentifier = '';
protected $consoleEnabled = 0;
@@ -146,6 +148,8 @@
'accountSecret' => 'bytes64',
'isEnrolledInMultiFactor' => 'bool',
'profileImageCache' => 'text255?',
+ 'availabilityCache' => 'text255?',
+ 'availabilityCacheTTL' => 'uint32?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
@@ -166,6 +170,8 @@
),
self::CONFIG_NO_MUTATE => array(
'profileImageCache' => true,
+ 'availabilityCache' => true,
+ 'availabilityCacheTTL' => true,
),
) + parent::getConfiguration();
}
@@ -721,7 +727,7 @@
/**
* @task availability
*/
- public function attachAvailability($availability) {
+ public function attachAvailability(array $availability) {
$this->availability = $availability;
return $this;
}
@@ -762,6 +768,50 @@
}
+ /**
+ * Get cached availability, if present.
+ *
+ * @return wild|null Cache data, or null if no cache is available.
+ * @task availability
+ */
+ public function getAvailabilityCache() {
+ $now = PhabricatorTime::getNow();
+ if ($this->availabilityCacheTTL <= $now) {
+ return null;
+ }
+
+ try {
+ return phutil_json_decode($this->availabilityCache);
+ } catch (Exception $ex) {
+ return null;
+ }
+ }
+
+
+ /**
+ * Write to the availability cache.
+ *
+ * @param wild Availability cache data.
+ * @param int|null Cache TTL.
+ * @return this
+ * @task availability
+ */
+ public function writeAvailabilityCache(array $availability, $ttl) {
+ $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
+ queryfx(
+ $this->establishConnection('w'),
+ 'UPDATE %T SET availabilityCache = %s, availabilityCacheTTL = %nd
+ WHERE id = %d',
+ $this->getTableName(),
+ json_encode($availability),
+ $ttl,
+ $this->getID());
+ unset($unguarded);
+
+ return $this;
+ }
+
+
/* -( Profile Image Cache )------------------------------------------------ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Oct 21, 9:00 AM (4 w, 7 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6711849
Default Alt Text
D12838.id30897.diff (8 KB)
Attached To
Mode
D12838: Add an availability cache for users
Attached
Detach File
Event Timeline
Log In to Comment