BackendChain.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <?php
  2. namespace Drupal\Core\Cache;
  3. /**
  4. * Defines a chained cache implementation for combining multiple cache backends.
  5. *
  6. * Can be used to combine two or more backends together to behave as if they
  7. * were a single backend.
  8. *
  9. * For example a slower, persistent storage engine could be combined with a
  10. * faster, volatile storage engine. When retrieving items from cache, they will
  11. * be fetched from the volatile backend first, only falling back to the
  12. * persistent backend if an item is not available. An item not present in the
  13. * volatile backend but found in the persistent one will be propagated back up
  14. * to ensure fast retrieval on the next request. On cache sets and deletes, both
  15. * backends will be invoked to ensure consistency.
  16. *
  17. * @see \Drupal\Core\Cache\ChainedFastBackend
  18. *
  19. * @ingroup cache
  20. */
  21. class BackendChain implements CacheBackendInterface, CacheTagsInvalidatorInterface {
  22. /**
  23. * Ordered list of CacheBackendInterface instances.
  24. *
  25. * @var array
  26. */
  27. protected $backends = [];
  28. /**
  29. * Constructs a new backend chain service instance.
  30. *
  31. * @param string|null $bin
  32. * (deprecated) The cache bin for which the object is created. The $bin
  33. * parameter is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0.
  34. *
  35. * @see https://www.drupal.org/node/3061125
  36. */
  37. public function __construct($bin = NULL) {
  38. if ($bin) {
  39. @trigger_error('The $bin parameter is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Omit the first parameter. See https://www.drupal.org/node/3061125', E_USER_DEPRECATED);
  40. }
  41. }
  42. /**
  43. * Appends a cache backend to the cache chain.
  44. *
  45. * @param CacheBackendInterface $backend
  46. * The cache backend to be appended to the cache chain.
  47. *
  48. * @return $this
  49. * The called object.
  50. */
  51. public function appendBackend(CacheBackendInterface $backend) {
  52. $this->backends[] = $backend;
  53. return $this;
  54. }
  55. /**
  56. * Prepends a cache backend to the cache chain.
  57. *
  58. * @param CacheBackendInterface $backend
  59. * The backend to be prepended to the cache chain.
  60. *
  61. * @return $this
  62. * The called object.
  63. */
  64. public function prependBackend(CacheBackendInterface $backend) {
  65. array_unshift($this->backends, $backend);
  66. return $this;
  67. }
  68. /**
  69. * {@inheritdoc}
  70. */
  71. public function get($cid, $allow_invalid = FALSE) {
  72. foreach ($this->backends as $index => $backend) {
  73. if (($return = $backend->get($cid, $allow_invalid)) !== FALSE) {
  74. // We found a result, propagate it to all missed backends.
  75. if ($index > 0) {
  76. for ($i = ($index - 1); 0 <= $i; --$i) {
  77. $this->backends[$i]->set($cid, $return->data, $return->expire, $return->tags);
  78. }
  79. }
  80. return $return;
  81. }
  82. }
  83. return FALSE;
  84. }
  85. /**
  86. * {@inheritdoc}
  87. */
  88. public function getMultiple(&$cids, $allow_invalid = FALSE) {
  89. $return = [];
  90. foreach ($this->backends as $index => $backend) {
  91. $items = $backend->getMultiple($cids, $allow_invalid);
  92. // Propagate the values that could be retrieved from the current cache
  93. // backend to all missed backends.
  94. if ($index > 0 && !empty($items)) {
  95. for ($i = ($index - 1); 0 <= $i; --$i) {
  96. foreach ($items as $cached) {
  97. $this->backends[$i]->set($cached->cid, $cached->data, $cached->expire, $cached->tags);
  98. }
  99. }
  100. }
  101. // Append the values to the previously retrieved ones.
  102. $return += $items;
  103. if (empty($cids)) {
  104. // No need to go further if we don't have any cid to fetch left.
  105. break;
  106. }
  107. }
  108. return $return;
  109. }
  110. /**
  111. * {@inheritdoc}
  112. */
  113. public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = []) {
  114. foreach ($this->backends as $backend) {
  115. $backend->set($cid, $data, $expire, $tags);
  116. }
  117. }
  118. /**
  119. * {@inheritdoc}
  120. */
  121. public function setMultiple(array $items) {
  122. foreach ($this->backends as $backend) {
  123. $backend->setMultiple($items);
  124. }
  125. }
  126. /**
  127. * {@inheritdoc}
  128. */
  129. public function delete($cid) {
  130. foreach ($this->backends as $backend) {
  131. $backend->delete($cid);
  132. }
  133. }
  134. /**
  135. * {@inheritdoc}
  136. */
  137. public function deleteMultiple(array $cids) {
  138. foreach ($this->backends as $backend) {
  139. $backend->deleteMultiple($cids);
  140. }
  141. }
  142. /**
  143. * {@inheritdoc}
  144. */
  145. public function deleteAll() {
  146. foreach ($this->backends as $backend) {
  147. $backend->deleteAll();
  148. }
  149. }
  150. /**
  151. * {@inheritdoc}
  152. */
  153. public function invalidate($cid) {
  154. foreach ($this->backends as $backend) {
  155. $backend->invalidate($cid);
  156. }
  157. }
  158. /**
  159. * {@inheritdoc}
  160. */
  161. public function invalidateMultiple(array $cids) {
  162. foreach ($this->backends as $backend) {
  163. $backend->invalidateMultiple($cids);
  164. }
  165. }
  166. /**
  167. * {@inheritdoc}
  168. */
  169. public function invalidateTags(array $tags) {
  170. foreach ($this->backends as $backend) {
  171. if ($backend instanceof CacheTagsInvalidatorInterface) {
  172. $backend->invalidateTags($tags);
  173. }
  174. }
  175. }
  176. /**
  177. * {@inheritdoc}
  178. */
  179. public function invalidateAll() {
  180. foreach ($this->backends as $backend) {
  181. $backend->invalidateAll();
  182. }
  183. }
  184. /**
  185. * {@inheritdoc}
  186. */
  187. public function garbageCollection() {
  188. foreach ($this->backends as $backend) {
  189. $backend->garbageCollection();
  190. }
  191. }
  192. /**
  193. * {@inheritdoc}
  194. */
  195. public function removeBin() {
  196. foreach ($this->backends as $backend) {
  197. $backend->removeBin();
  198. }
  199. }
  200. }