Exponential 5.x Kernel 7.5.40 Exponential New Stack (Symfony-based) Kernel — PHP Class Reference

TransactionalInMemoryCacheAdapter.php
Go to the documentation of this file.
1 <?php
2
7 declare(strict_types=1);
8
9 namespace eZ\Publish\Core\Persistence\Cache\Adapter;
10
11 use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
12 use Psr\Cache\CacheItemInterface;
13 use Symfony\Component\Cache\CacheItem;
14
20 class TransactionalInMemoryCacheAdapter implements TransactionAwareAdapterInterface
21 {
23 protected $sharedPool;
24
26 private $inMemoryPools;
27
29 protected $transactionDepth;
30
32 protected $deferredTagsInvalidation;
33
35 protected $deferredItemsDeletion;
36
38 protected $setCacheItemAsMiss;
39
47 public function __construct(
48 TagAwareAdapterInterface $sharedPool,
49 iterable $inMemoryPools,
50 int $transactionDepth = 0,
51 array $deferredTagsInvalidation = [],
52 array $deferredItemsDeletion = []
53 ) {
54 $this->sharedPool = $sharedPool;
55 $this->inMemoryPools = $inMemoryPools;
56 $this->transactionDepth = $transactionDepth;
57 $this->deferredTagsInvalidation = empty($deferredTagsInvalidation) ? [] : \array_fill_keys($deferredTagsInvalidation, true);
58 $this->deferredItemsDeletion = empty($deferredItemsDeletion) ? [] : \array_fill_keys($deferredItemsDeletion, true);
59 // To modify protected $isHit when items are a "miss" based on deferred delete/invalidation during transactions
60 $this->setCacheItemAsMiss = \Closure::bind(
61 static function (CacheItem $item) {
62 // ... Might not work for anything but new items
63 $item->isHit = false;
64 },
65 null,
66 CacheItem::class
67 );
68 }
69
73 public function getItem($key)
74 {
75 return $this->markItemsAsDeferredMissIfNeeded(
76 [$this->sharedPool->getItem($key)]
77 )[0];
78 }
79
83 public function getItems(array $keys = [])
84 {
85 return $this->markItemsAsDeferredMissIfNeeded(
86 $this->sharedPool->getItems($keys)
87 );
88 }
89
93 public function hasItem($key)
94 {
95 if (isset($this->deferredItemsDeletion[$key])) {
96 return false;
97 }
98
99 return $this->sharedPool->hasItem($key);
100 }
101
105 public function deleteItem($key)
106 {
107 foreach ($this->inMemoryPools as $inMemory) {
108 $inMemory->deleteMulti([$key]);
109 }
110
111 if ($this->transactionDepth > 0) {
112 $this->deferredItemsDeletion[$key] = true;
113
114 return true;
115 }
116
117 return $this->sharedPool->deleteItem($key);
118 }
119
123 public function deleteItems(array $keys)
124 {
125 foreach ($this->inMemoryPools as $inMemory) {
126 $inMemory->deleteMulti($keys);
127 }
128
129 if ($this->transactionDepth > 0) {
130 $this->deferredItemsDeletion += \array_fill_keys($keys, true);
131
132 return true;
133 }
134
135 return $this->sharedPool->deleteItems($keys);
136 }
137
141 public function invalidateTags(array $tags)
142 {
143 // No tracking of tags in in-memory, as it's anyway meant to only optimize for reads (GETs) and not writes.
144 $this->clearInMemoryPools();
145
146 if ($this->transactionDepth > 0) {
147 $this->deferredTagsInvalidation += \array_fill_keys($tags, true);
148
149 return true;
150 }
151
152 return $this->sharedPool->invalidateTags($tags);
153 }
154
158 public function clear()
159 {
160 $this->clearInMemoryPools();
161
162 // @todo Should we trow RunTime error or add support deferring full cache clearing?
163 $this->transactionDepth = 0;
164 $this->deferredItemsDeletion = [];
165 $this->deferredTagsInvalidation = [];
166
167 return $this->sharedPool->clear();
168 }
169
173 public function save(CacheItemInterface $item)
174 {
175 if ($this->transactionDepth > 0) {
176 $this->deferredItemsDeletion[$item->getKey()] = true;
177
178 return true;
179 }
180
181 return $this->sharedPool->save($item);
182 }
183
187 public function beginTransaction(): void
188 {
189 ++$this->transactionDepth;
190 }
191
195 public function commitTransaction(): void
196 {
197 if ($this->transactionDepth === 0) {
198 // ignore, might have been a previous rollback
199 return;
200 }
201
202 --$this->transactionDepth;
203
204 // Once we reach 0 transaction count, sent out deferred deletes/invalidations to shared pool
205 if ($this->transactionDepth === 0) {
206 if (!empty($this->deferredItemsDeletion)) {
207 $this->sharedPool->deleteItems(\array_keys($this->deferredItemsDeletion));
208 $this->deferredItemsDeletion = [];
209 }
210
211 if (!empty($this->deferredTagsInvalidation)) {
212 $this->sharedPool->invalidateTags(\array_keys($this->deferredTagsInvalidation));
213 $this->deferredTagsInvalidation = [];
214 }
215 }
216 }
217
221 public function rollbackTransaction(): void
222 {
223 $this->transactionDepth = 0;
224 $this->deferredItemsDeletion = [];
225 $this->deferredTagsInvalidation = [];
226
227 $this->clearInMemoryPools();
228 }
229
235 public function saveDeferred(CacheItemInterface $item)
236 {
237 return $this->sharedPool->saveDeferred($item);
238 }
239
245 public function commit()
246 {
247 return $this->sharedPool->commit();
248 }
249
257 private function markItemsAsDeferredMissIfNeeded(iterable $items)
258 {
259 if ($this->transactionDepth === 0) {
260 return $items;
261 }
262
263 // In case of $items being generator we map items over to new array as it can't be iterated several times
264 $iteratedItems = [];
265 $fnSetCacheItemAsMiss = $this->setCacheItemAsMiss;
266 foreach ($items as $key => $item) {
267 $iteratedItems[$key] = $item;
268
269 if (!$item->isHit()) {
270 continue;
271 }
272
273 if ($this->itemIsDeferredMiss($item)) {
274 $fnSetCacheItemAsMiss($item);
275 }
276 }
277
278 return $iteratedItems;
279 }
280
286 private function itemIsDeferredMiss(CacheItem $item): bool
287 {
288 if (isset($this->deferredItemsDeletion[$item->getKey()])) {
289 return true;
290 }
291
292 foreach ($item->getPreviousTags() as $tag) {
293 if (isset($this->deferredTagsInvalidation[$tag])) {
294 return true;
295 }
296 }
297
298 return false;
299 }
300
301 ################################################################################
302 # TEMPORARY COMPATIBILITY LAYER - 2026-02-05 #
303 # Added setContainer() stub for Symfony container compilation compatibility #
304 # This method is called during container service definition but is not used #
305 # in the actual cache adapter runtime. Simple no-op implementation needed. #
306 ################################################################################
315 public function setContainer($container = null)
316 {
317 // No-op stub for container compilation compatibility
318 // The container is not needed for TransactionalInMemoryCacheAdapter operations
319 }
320 ################################################################################
321
322 private function clearInMemoryPools(): void
323 {
324 foreach ($this->inMemoryPools as $inMemory) {
325 $inMemory->clear();
326 }
327 }
328 }
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter
Internal proxy adapter invalidating our isolated in-memory cache, and defer shared pool changes durin...
Definition: TransactionalInMemoryCacheAdapter.php:21
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\deleteItem
deleteItem($key)
{}
Definition: TransactionalInMemoryCacheAdapter.php:105
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\markItemsAsDeferredMissIfNeeded
markItemsAsDeferredMissIfNeeded(iterable $items)
For use by getItem(s) to mark items as a miss if it's going to be cleared on transaction commit.
Definition: TransactionalInMemoryCacheAdapter.php:257
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\hasItem
hasItem($key)
{}
Definition: TransactionalInMemoryCacheAdapter.php:93
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\$deferredTagsInvalidation
$deferredTagsInvalidation
Definition: TransactionalInMemoryCacheAdapter.php:32
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\$transactionDepth
$transactionDepth
Definition: TransactionalInMemoryCacheAdapter.php:29
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\$inMemoryPools
$inMemoryPools
Definition: TransactionalInMemoryCacheAdapter.php:26
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\itemIsDeferredMiss
itemIsDeferredMiss(CacheItem $item)
Definition: TransactionalInMemoryCacheAdapter.php:286
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\clear
clear()
{}
Definition: TransactionalInMemoryCacheAdapter.php:158
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\getItem
getItem($key)
{}
Definition: TransactionalInMemoryCacheAdapter.php:73
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\deleteItems
deleteItems(array $keys)
{}
Definition: TransactionalInMemoryCacheAdapter.php:123
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\$deferredItemsDeletion
$deferredItemsDeletion
Definition: TransactionalInMemoryCacheAdapter.php:35
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\__construct
__construct(TagAwareAdapterInterface $sharedPool, iterable $inMemoryPools, int $transactionDepth=0, array $deferredTagsInvalidation=[], array $deferredItemsDeletion=[])
Definition: TransactionalInMemoryCacheAdapter.php:47
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\rollbackTransaction
rollbackTransaction()
{Called when transaction is rolled back.}
Definition: TransactionalInMemoryCacheAdapter.php:221
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\save
save(CacheItemInterface $item)
{}
Definition: TransactionalInMemoryCacheAdapter.php:173
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\clearInMemoryPools
clearInMemoryPools()
Definition: TransactionalInMemoryCacheAdapter.php:322
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\commitTransaction
commitTransaction()
{Called when transaction is committed.WARNING: Must be called just AFTER database commit,...
Definition: TransactionalInMemoryCacheAdapter.php:195
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\$sharedPool
$sharedPool
Definition: TransactionalInMemoryCacheAdapter.php:23
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\commit
commit()
{}
Definition: TransactionalInMemoryCacheAdapter.php:245
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\invalidateTags
invalidateTags(array $tags)
{}
Definition: TransactionalInMemoryCacheAdapter.php:141
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\getItems
getItems(array $keys=[])
{}
Definition: TransactionalInMemoryCacheAdapter.php:83
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\$setCacheItemAsMiss
$setCacheItemAsMiss
Definition: TransactionalInMemoryCacheAdapter.php:38
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\setContainer
setContainer($container=null)
Temporary stub for Symfony container compatibility.
Definition: TransactionalInMemoryCacheAdapter.php:315
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\beginTransaction
beginTransaction()
{Called when transaction starts.}
Definition: TransactionalInMemoryCacheAdapter.php:187
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionalInMemoryCacheAdapter\saveDeferred
saveDeferred(CacheItemInterface $item)
{}
Definition: TransactionalInMemoryCacheAdapter.php:235
eZ\Publish\Core\Persistence\Cache\Adapter\TransactionAwareAdapterInterface
Interface for cache adapter which is aware of persistence transactions.
Definition: TransactionAwareAdapterInterface.php:22
eZ\Publish\Core\Persistence\Cache\Adapter
Definition: TransactionalInMemoryCacheAdapter.php:9
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.