@@ -33,11 +33,14 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R
33
33
private $ getTagsByKey ;
34
34
private $ invalidateTags ;
35
35
private $ tags ;
36
+ private $ knownTagVersions = array ();
37
+ private $ knownTagVersionsTtl ;
36
38
37
- public function __construct (AdapterInterface $ itemsPool , AdapterInterface $ tagsPool = null )
39
+ public function __construct (AdapterInterface $ itemsPool , AdapterInterface $ tagsPool = null , $ knownTagVersionsTtl = 0.15 )
38
40
{
39
41
$ this ->pool = $ itemsPool ;
40
42
$ this ->tags = $ tagsPool ?: $ itemsPool ;
43
+ $ this ->knownTagVersionsTtl = $ knownTagVersionsTtl ;
41
44
$ this ->createCacheItem = \Closure::bind (
42
45
function ($ key , $ value , CacheItem $ protoItem ) {
43
46
$ item = new CacheItem ();
@@ -87,8 +90,7 @@ function ($deferred) {
87
90
);
88
91
$ this ->invalidateTags = \Closure::bind (
89
92
function (AdapterInterface $ tagsAdapter , array $ tags ) {
90
- foreach ($ tagsAdapter ->getItems ($ tags ) as $ v ) {
91
- $ v ->set (1 + (int ) $ v ->get ());
93
+ foreach ($ tags as $ v ) {
92
94
$ v ->defaultLifetime = 0 ;
93
95
$ v ->expiry = null ;
94
96
$ tagsAdapter ->saveDeferred ($ v );
@@ -106,14 +108,42 @@ function (AdapterInterface $tagsAdapter, array $tags) {
106
108
*/
107
109
public function invalidateTags (array $ tags )
108
110
{
109
- foreach ($ tags as $ k => $ tag ) {
110
- if ('' !== $ tag && \is_string ($ tag )) {
111
- $ tags [$ k ] = $ tag .static ::TAGS_PREFIX ;
111
+ $ ok = true ;
112
+ $ tagsByKey = array ();
113
+ $ invalidatedTags = array ();
114
+ foreach ($ tags as $ tag ) {
115
+ CacheItem::validateKey ($ tag );
116
+ $ invalidatedTags [$ tag ] = 0 ;
117
+ }
118
+
119
+ if ($ this ->deferred ) {
120
+ $ items = $ this ->deferred ;
121
+ foreach ($ items as $ key => $ item ) {
122
+ if (!$ this ->pool ->saveDeferred ($ item )) {
123
+ unset($ this ->deferred [$ key ]);
124
+ $ ok = false ;
125
+ }
112
126
}
127
+
128
+ $ f = $ this ->getTagsByKey ;
129
+ $ tagsByKey = $ f ($ items );
130
+ $ this ->deferred = array ();
131
+ }
132
+
133
+ $ tagVersions = $ this ->getTagVersions ($ tagsByKey , $ invalidatedTags );
134
+ $ f = $ this ->createCacheItem ;
135
+
136
+ foreach ($ tagsByKey as $ key => $ tags ) {
137
+ $ this ->pool ->saveDeferred ($ f (static ::TAGS_PREFIX .$ key , array_intersect_key ($ tagVersions , $ tags ), $ items [$ key ]));
138
+ }
139
+ $ ok = $ this ->pool ->commit () && $ ok ;
140
+
141
+ if ($ invalidatedTags ) {
142
+ $ f = $ this ->invalidateTags ;
143
+ $ ok = $ f ($ this ->tags , $ invalidatedTags ) && $ ok ;
113
144
}
114
- $ f = $ this ->invalidateTags ;
115
145
116
- return $ f ( $ this -> tags , $ tags ) ;
146
+ return $ ok ;
117
147
}
118
148
119
149
/**
@@ -132,7 +162,7 @@ public function hasItem($key)
132
162
}
133
163
134
164
foreach ($ this ->getTagVersions (array ($ itemTags )) as $ tag => $ version ) {
135
- if ($ itemTags [$ tag ] !== $ version ) {
165
+ if ($ itemTags [$ tag ] !== $ version && 1 !== $ itemTags [ $ tag ] - $ version ) {
136
166
return false ;
137
167
}
138
168
}
@@ -241,29 +271,7 @@ public function saveDeferred(CacheItemInterface $item)
241
271
*/
242
272
public function commit ()
243
273
{
244
- $ ok = true ;
245
-
246
- if ($ this ->deferred ) {
247
- $ items = $ this ->deferred ;
248
- foreach ($ items as $ key => $ item ) {
249
- if (!$ this ->pool ->saveDeferred ($ item )) {
250
- unset($ this ->deferred [$ key ]);
251
- $ ok = false ;
252
- }
253
- }
254
-
255
- $ f = $ this ->getTagsByKey ;
256
- $ tagsByKey = $ f ($ items );
257
- $ this ->deferred = array ();
258
- $ tagVersions = $ this ->getTagVersions ($ tagsByKey );
259
- $ f = $ this ->createCacheItem ;
260
-
261
- foreach ($ tagsByKey as $ key => $ tags ) {
262
- $ this ->pool ->saveDeferred ($ f (static ::TAGS_PREFIX .$ key , array_intersect_key ($ tagVersions , $ tags ), $ items [$ key ]));
263
- }
264
- }
265
-
266
- return $ this ->pool ->commit () && $ ok ;
274
+ return $ this ->invalidateTags (array ());
267
275
}
268
276
269
277
public function __destruct ()
@@ -294,7 +302,7 @@ private function generateItems($items, array $tagKeys)
294
302
295
303
foreach ($ itemTags as $ key => $ tags ) {
296
304
foreach ($ tags as $ tag => $ version ) {
297
- if ($ tagVersions [$ tag ] !== $ version ) {
305
+ if ($ tagVersions [$ tag ] !== $ version && 1 !== $ version - $ tagVersions [ $ tag ] ) {
298
306
unset($ itemTags [$ key ]);
299
307
continue 2 ;
300
308
}
@@ -310,23 +318,54 @@ private function generateItems($items, array $tagKeys)
310
318
}
311
319
}
312
320
313
- private function getTagVersions (array $ tagsByKey )
321
+ private function getTagVersions (array $ tagsByKey, array & $ invalidatedTags = array () )
314
322
{
315
- $ tagVersions = array () ;
323
+ $ tagVersions = $ invalidatedTags ;
316
324
317
325
foreach ($ tagsByKey as $ tags ) {
318
326
$ tagVersions += $ tags ;
319
327
}
320
328
321
- if ($ tagVersions ) {
322
- $ tags = array ();
323
- foreach ($ tagVersions as $ tag => $ version ) {
324
- $ tagVersions [$ tag ] = $ tag .static ::TAGS_PREFIX ;
325
- $ tags [$ tag .static ::TAGS_PREFIX ] = $ tag ;
329
+ if (!$ tagVersions ) {
330
+ return array ();
331
+ }
332
+
333
+ if (!$ fetchTagVersions = 1 !== \func_num_args ()) {
334
+ foreach ($ tagsByKey as $ tags ) {
335
+ foreach ($ tags as $ tag => $ version ) {
336
+ if ($ tagVersions [$ tag ] > $ version ) {
337
+ $ tagVersions [$ tag ] = $ version ;
338
+ }
339
+ }
340
+ }
341
+ }
342
+
343
+ $ now = microtime (true );
344
+ $ tags = array ();
345
+ foreach ($ tagVersions as $ tag => $ version ) {
346
+ $ tags [$ tag .static ::TAGS_PREFIX ] = $ tag ;
347
+ if ($ fetchTagVersions || !isset ($ this ->knownTagVersions [$ tag ])) {
348
+ continue ;
349
+ }
350
+ $ version -= $ this ->knownTagVersions [$ tag ][1 ];
351
+ if ((0 !== $ version && 1 !== $ version ) || $ this ->knownTagVersionsTtl > $ now - $ this ->knownTagVersions [$ tag ][0 ]) {
352
+ // reuse previously fetched tag versions up to the ttl, unless we are storing items or a potential miss arises
353
+ $ fetchTagVersions = true ;
354
+ } else {
355
+ $ this ->knownTagVersions [$ tag ][1 ] += $ version ;
326
356
}
327
- foreach ($ this ->tags ->getItems ($ tagVersions ) as $ tag => $ version ) {
328
- $ tagVersions [$ tags [$ tag ]] = $ version ->get () ?: 0 ;
357
+ }
358
+
359
+ if (!$ fetchTagVersions ) {
360
+ return $ tagVersions ;
361
+ }
362
+
363
+ foreach ($ this ->tags ->getItems (array_keys ($ tags )) as $ tag => $ version ) {
364
+ $ tagVersions [$ tag = $ tags [$ tag ]] = $ version ->get () ?: 0 ;
365
+ if (isset ($ invalidatedTags [$ tag ])) {
366
+ $ invalidatedTags [$ tag ] = $ version ->set (++$ tagVersions [$ tag ]);
329
367
}
368
+ $ this ->knownTagVersions [$ tag ] = array ($ now , $ tagVersions [$ tag ]);
330
369
}
331
370
332
371
return $ tagVersions ;
0 commit comments