getMulti() публичный Метод

Return value will be an associative array in [key => value] format. Keys missing in cache will be omitted from the array. Optionally, an 2nd variable can be passed to this function. It will be filled with values that can be used for cas(), in an associative array in [key => token] format. Keys missing in cache will be omitted from the array. getMulti is preferred over multiple individual get operations as you'll get them all in 1 request.
public getMulti ( array $keys, array &$tokens = null ) : mixed[]
$keys array
$tokens array Will be filled with the CAS tokens, in [key => token] format
Результат mixed[] [key => value]
Пример #1
0
 /**
  * {@inheritdoc}
  */
 public function getMulti(array $keys, array &$tokens = null)
 {
     // retrieve all that we can from local cache
     $values = $this->local->getMulti($keys);
     $tokens = array();
     // short-circuit reading from real cache if we have an uncommitted flush
     if (!$this->suspend) {
         // figure out which missing key we need to get from real cache
         $keys = array_diff($keys, array_keys($values));
         foreach ($keys as $i => $key) {
             // don't reach out to real cache for keys that are about to be gone
             if ($this->local->expired($key)) {
                 unset($keys[$i]);
             }
         }
         // fetch missing values from real cache
         if ($keys) {
             $missing = $this->cache->getMulti($keys);
             $values += $missing;
         }
     }
     // any tokens we get will be unreliable, so generate some replacements
     // (more elaborate explanation in get())
     foreach ($values as $key => $value) {
         $token = uniqid();
         $tokens[$key] = $token;
         $this->tokens[$token] = serialize($value);
     }
     return $values;
 }
Пример #2
0
 /**
  * {@inheritdoc}
  */
 public function has($key)
 {
     if (!is_string($key)) {
         throw new InvalidArgumentException('Invalid key: ' . serialize($key) . '. Must be string.');
     }
     // KeyValueStore::get returns false for cache misses (which could also
     // be confused for a `false` value), so we'll check existence with getMulti
     $multi = $this->store->getMulti(array($key));
     return isset($multi[$key]);
 }
Пример #3
0
 /**
  * Since we can't perform true atomic transactions, we'll fake it.
  * Most of the operations (set, touch, ...) can't fail. We'll do those last.
  * We'll first schedule the operations that can fail (cas, replace, add)
  * to minimize chances of another process overwriting those values in the
  * meantime.
  * But it could still happen, so we should fetch the current values for all
  * unsafe operations. If the transaction fails, we can then restore them.
  *
  * @return array[] Array of 2 [key => value] maps: current & scheduled data
  */
 protected function generateRollback()
 {
     $keys = array();
     $new = array();
     foreach ($this->keys as $key => $data) {
         $operation = $data[0];
         // we only need values for cas & replace - recovering from an 'add'
         // is just deleting the value...
         if (in_array($operation, array('cas', 'replace'))) {
             $keys[] = $key;
             $new[$key] = $data[2]['value'];
         }
     }
     if (empty($keys)) {
         return array(array(), array());
     }
     // fetch the existing data & return the planned new data as well
     $current = $this->cache->getMulti($keys);
     return array($current, $new);
 }
Пример #4
0
 /**
  * Resolve all unresolved keys at once.
  */
 protected function resolve()
 {
     $keys = array_unique(array_values($this->unresolved));
     $values = $this->store->getMulti($keys);
     foreach ($this->unresolved as $unique => $key) {
         if (!array_key_exists($key, $values)) {
             // key doesn't exist in cache
             continue;
         }
         /*
          * In theory, there could've been multiple unresolved requests for
          * the same cache key. In the case of objects, we'll clone them
          * to make sure that when the value for 1 item is manipulated, it
          * doesn't affect the value of the other item (because those objects
          * would be passed by-ref without the cloning)
          */
         $value = $values[$key];
         $value = is_object($value) ? clone $value : $value;
         $this->resolved[$unique] = $value;
     }
     $this->unresolved = array();
 }
Пример #5
0
 /**
  * {@inheritdoc}
  */
 public function getMulti(array $keys, array &$tokens = null)
 {
     // fetch both requested keys + stampede protection indicators at once
     $stampedeKeys = array_combine($keys, array_map(array($this, 'stampedeKey'), $keys));
     $values = $this->cache->getMulti(array_merge($keys, $stampedeKeys), $tokens);
     // figure out which of the requested keys are protected, and which need
     // protection (=currently empty & not yet protected)
     $protected = array_keys(array_intersect($stampedeKeys, array_keys($values)));
     $protect = array_diff($keys, array_keys($values), $protected);
     // protect keys that we couldn't find, and remove them from the list of
     // keys we want results from, because we'll keep fetching empty keys
     // (that are currently protected)
     $done = $this->protect($protect);
     $keys = array_diff($keys, $done);
     // we may have failed to protect some keys after all (race condition
     // with another process), in which case we also have to keep polling
     // those keys (which the other process is likely working on already)
     $protected += array_diff($protect, $done);
     // we over-fetched (to include stampede indicators), now limit the
     // results to only the keys we requested
     $results = array_intersect_key($values, array_flip($keys));
     $tokens = array_intersect_key($tokens, $results);
     // we may not have been able to retrieve all keys yet: some may have
     // been "protected" (and are being regenerated in another process) in
     // which case we'll retry a couple of times, hoping the other process
     // stores the new value in the meantime
     $attempts = $this->attempts;
     while (--$attempts > 0 && !empty($protected) && $this->sleep()) {
         $values = $this->cache->getMulti($protected, $tokens2);
         $results += array_intersect_key($values, array_flip($keys));
         $tokens += array_intersect_key($tokens2, array_flip($keys));
         // don't keep polling for values we just fetched...
         $protected = array_diff($protected, array_keys($values));
     }
     return $results;
 }