ChainCache.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. <?php
  2. namespace Doctrine\Common\Cache;
  3. use Traversable;
  4. use function array_values;
  5. use function count;
  6. use function iterator_to_array;
  7. /**
  8. * Cache provider that allows to easily chain multiple cache providers
  9. */
  10. class ChainCache extends CacheProvider
  11. {
  12. /** @var CacheProvider[] */
  13. private $cacheProviders = [];
  14. /** @var int */
  15. private $defaultLifeTimeForDownstreamCacheProviders = 0;
  16. /**
  17. * @param CacheProvider[] $cacheProviders
  18. */
  19. public function __construct($cacheProviders = [])
  20. {
  21. $this->cacheProviders = $cacheProviders instanceof Traversable
  22. ? iterator_to_array($cacheProviders, false)
  23. : array_values($cacheProviders);
  24. }
  25. public function setDefaultLifeTimeForDownstreamCacheProviders(int $defaultLifeTimeForDownstreamCacheProviders) : void
  26. {
  27. $this->defaultLifeTimeForDownstreamCacheProviders = $defaultLifeTimeForDownstreamCacheProviders;
  28. }
  29. /**
  30. * {@inheritDoc}
  31. */
  32. public function setNamespace($namespace)
  33. {
  34. parent::setNamespace($namespace);
  35. foreach ($this->cacheProviders as $cacheProvider) {
  36. $cacheProvider->setNamespace($namespace);
  37. }
  38. }
  39. /**
  40. * {@inheritDoc}
  41. */
  42. protected function doFetch($id)
  43. {
  44. foreach ($this->cacheProviders as $key => $cacheProvider) {
  45. if ($cacheProvider->doContains($id)) {
  46. $value = $cacheProvider->doFetch($id);
  47. // We populate all the previous cache layers (that are assumed to be faster)
  48. for ($subKey = $key - 1; $subKey >= 0; $subKey--) {
  49. $this->cacheProviders[$subKey]->doSave($id, $value, $this->defaultLifeTimeForDownstreamCacheProviders);
  50. }
  51. return $value;
  52. }
  53. }
  54. return false;
  55. }
  56. /**
  57. * {@inheritdoc}
  58. */
  59. protected function doFetchMultiple(array $keys)
  60. {
  61. /** @var CacheProvider[] $traversedProviders */
  62. $traversedProviders = [];
  63. $keysCount = count($keys);
  64. $fetchedValues = [];
  65. foreach ($this->cacheProviders as $key => $cacheProvider) {
  66. $fetchedValues = $cacheProvider->doFetchMultiple($keys);
  67. // We populate all the previous cache layers (that are assumed to be faster)
  68. if (count($fetchedValues) === $keysCount) {
  69. foreach ($traversedProviders as $previousCacheProvider) {
  70. $previousCacheProvider->doSaveMultiple($fetchedValues, $this->defaultLifeTimeForDownstreamCacheProviders);
  71. }
  72. return $fetchedValues;
  73. }
  74. $traversedProviders[] = $cacheProvider;
  75. }
  76. return $fetchedValues;
  77. }
  78. /**
  79. * {@inheritDoc}
  80. */
  81. protected function doContains($id)
  82. {
  83. foreach ($this->cacheProviders as $cacheProvider) {
  84. if ($cacheProvider->doContains($id)) {
  85. return true;
  86. }
  87. }
  88. return false;
  89. }
  90. /**
  91. * {@inheritDoc}
  92. */
  93. protected function doSave($id, $data, $lifeTime = 0)
  94. {
  95. $stored = true;
  96. foreach ($this->cacheProviders as $cacheProvider) {
  97. $stored = $cacheProvider->doSave($id, $data, $lifeTime) && $stored;
  98. }
  99. return $stored;
  100. }
  101. /**
  102. * {@inheritdoc}
  103. */
  104. protected function doSaveMultiple(array $keysAndValues, $lifetime = 0)
  105. {
  106. $stored = true;
  107. foreach ($this->cacheProviders as $cacheProvider) {
  108. $stored = $cacheProvider->doSaveMultiple($keysAndValues, $lifetime) && $stored;
  109. }
  110. return $stored;
  111. }
  112. /**
  113. * {@inheritDoc}
  114. */
  115. protected function doDelete($id)
  116. {
  117. $deleted = true;
  118. foreach ($this->cacheProviders as $cacheProvider) {
  119. $deleted = $cacheProvider->doDelete($id) && $deleted;
  120. }
  121. return $deleted;
  122. }
  123. /**
  124. * {@inheritdoc}
  125. */
  126. protected function doDeleteMultiple(array $keys)
  127. {
  128. $deleted = true;
  129. foreach ($this->cacheProviders as $cacheProvider) {
  130. $deleted = $cacheProvider->doDeleteMultiple($keys) && $deleted;
  131. }
  132. return $deleted;
  133. }
  134. /**
  135. * {@inheritDoc}
  136. */
  137. protected function doFlush()
  138. {
  139. $flushed = true;
  140. foreach ($this->cacheProviders as $cacheProvider) {
  141. $flushed = $cacheProvider->doFlush() && $flushed;
  142. }
  143. return $flushed;
  144. }
  145. /**
  146. * {@inheritDoc}
  147. */
  148. protected function doGetStats()
  149. {
  150. // We return all the stats from all adapters
  151. $stats = [];
  152. foreach ($this->cacheProviders as $cacheProvider) {
  153. $stats[] = $cacheProvider->doGetStats();
  154. }
  155. return $stats;
  156. }
  157. }