diff --git a/include/ajax.search.php b/include/ajax.search.php index dbc0a291b86d3c7bebb6f1c67333735b23739b9e..fabe2d810fdd8e694d566b418b656c028e94a916 100644 --- a/include/ajax.search.php +++ b/include/ajax.search.php @@ -395,7 +395,7 @@ class SearchAjaxAPI extends AjaxController { if ($ids && is_array($ids)) $criteria = array('id__in' => $ids); - $counts = SavedQueue::ticketsCount($thisstaff, $criteria, 'q'); + $counts = SavedQueue::counts($thisstaff, $criteria); Http::response(200, false, 'application/json'); return $this->encode($counts); } diff --git a/include/class.search.php b/include/class.search.php index aa2919910bc918f5843b7c247e986bac6a5263a2..29dd562fc2c38633824950abd3921cf437ae95f0 100644 --- a/include/class.search.php +++ b/include/class.search.php @@ -848,18 +848,40 @@ class SavedQueue extends CustomQueue { return (!$errors); } - static function ticketsCount($agent, $criteria=array(), - $prefix='') { + function getCount($agent, $cached=true) { + $criteria = $cached ? array() : array('id' => $this->getId()); + $counts = self::counts($agent, $criteria, $cached); + return $counts["q{$this->getId()}"] ?: 0; + } + + // Get ticket counts for queues the agent has acces to. + static function counts($agent, $criteria=array(), $cached=true) { if (!$agent instanceof Staff) return array(); - if (function_exists('apcu_store')) { - $key = "counts.queues.{$agent->getId()}.".SECRET_SALT; - $cached = false; - $counts = apcu_fetch($key, $cached); - if ($cached === true) - return $counts; + // Cache TLS in seconds + $ttl = 3600; + // Cache key based on agent and salt of the installation + $key = "counts.queues.{$agent->getId()}.".SECRET_SALT; + if ($criteria && is_array($criteria)) // Consider additional criteria. + $key .= '.'.md5(serialize($criteria)); + + // only consider cache if requesed + if ($cached) { + if (function_exists('apcu_store')) { + $found = false; + $counts = apcu_fetch($key, $found); + if ($found === true) + return $counts; + } elseif (isset($_SESSION[$key]) + && isset($_SESSION[$key]['qcount']) + && (time() - $_SESSION[$key]['time']) < $ttl) { + return $_SESSION[$key]['qcount']; + } else { + // Auto clear missed session cache (if any) + unset($_SESSION[$key]); + } } $queues = static::objects() @@ -868,7 +890,7 @@ class SavedQueue extends CustomQueue { 'staff_id' => $agent->getId(), ))); - if ($criteria) + if ($criteria && is_array($criteria)) $queues->filter($criteria); $query = Ticket::objects(); @@ -879,15 +901,18 @@ class SavedQueue extends CustomQueue { $Q = $queue->getBasicQuery(); $expr = SqlCase::N()->when(new SqlExpr(new Q($Q->constraints)), new SqlField('ticket_id')); $query->aggregate(array( - "$prefix{$queue->id}" => SqlAggregate::COUNT($expr, true) + "q{$queue->id}" => SqlAggregate::COUNT($expr, true) )); } $counts = $query->values()->one(); - + // Always cache the results if (function_exists('apcu_store')) { - $key = "counts.queues.{$agent->getId()}.".SECRET_SALT; - apcu_store($key, $counts, 3600); + apcu_store($key, $counts, $ttl); + } else { + // Poor man's cache + $_SESSION[$key]['qcount'] = $counts; + $_SESSION[$key]['time'] = time(); } return $counts; @@ -895,9 +920,11 @@ class SavedQueue extends CustomQueue { static function clearCounts() { if (function_exists('apcu_store')) { - $regex = '/^counts.queues.\d+.' . preg_quote(SECRET_SALT, '/') . '$/'; - foreach (new APCUIterator($regex, APC_ITER_KEY) as $key) { - apcu_delete($key); + if (class_exists('APCUIterator')) { + $regex = '/^counts.queues.\d+.' . preg_quote(SECRET_SALT, '/') . '$/'; + foreach (new APCUIterator($regex, APC_ITER_KEY) as $key) { + apcu_delete($key); + } } // Also clear rough counts apcu_delete("rough.counts.".SECRET_SALT); diff --git a/include/staff/templates/queue-tickets.tmpl.php b/include/staff/templates/queue-tickets.tmpl.php index 205ac43c339a21b1b9b89927f629fec6f78e5bb0..10a4cffba2e9fecb826ecba0e7b18837f12f1fac 100644 --- a/include/staff/templates/queue-tickets.tmpl.php +++ b/include/staff/templates/queue-tickets.tmpl.php @@ -76,7 +76,7 @@ if (!$sorted && isset($sort['queuesort'])) { $page = ($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1; $pageNav = new Pagenate(PHP_INT_MAX, $page, PAGE_LIMIT); $tickets = $pageNav->paginateSimple($tickets); -$count = $queue->getRoughCount(); +$count = $queue->getCount($thisstaff); $pageNav->setTotal($count, true); $pageNav->setURL('tickets.php', $args); ?> diff --git a/scp/autocron.php b/scp/autocron.php index 170ab3a8b421286bdfe1db6a648a13e7b971946d..5f5da4fb29747af6e32e9c10533de6ea98c11527 100644 --- a/scp/autocron.php +++ b/scp/autocron.php @@ -45,6 +45,11 @@ if ($sec < 180 || !$ost || $ost->isUpgradePending()) require_once(INCLUDE_DIR.'class.cron.php'); +// Run tickets count every 3rd run or so... force new count by skipping cached +// results +if (mt_rand(1, 12) == 3) + SavedQueue::counts($thisstaff, array(), false); + // Clear staff obj to avoid false credit internal notes & auto-assignment $thisstaff = null;