|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace MatthiasMullie\Scrapbook\Buffered\Utils; |
|
4
|
|
|
|
|
5
|
|
|
use MatthiasMullie\Scrapbook\Adapters\MemoryStore; |
|
6
|
|
|
|
|
7
|
|
|
/** |
|
8
|
|
|
* This is a helper class for BufferedStore & TransactionalStore, which buffer |
|
9
|
|
|
* real cache requests in memory. |
|
10
|
|
|
* The memory-part can easily be handled by MemoryStore. There's just 1 gotcha: |
|
11
|
|
|
* when an item is to be deleted (but not yet committed), it needs to be deleted |
|
12
|
|
|
* from the MemoryStore too, but we need to be able to make a distinction |
|
13
|
|
|
* between "this is deleted" and "this value is not known in this memory cache, |
|
14
|
|
|
* fall back to real cache". |
|
15
|
|
|
* |
|
16
|
|
|
* This is where this class comes in to play: we'll add an additional "expired" |
|
17
|
|
|
* method, which allows BufferedStore to just expire the keys that are supposed |
|
18
|
|
|
* to be deleted (instead of deleting them) - then we can keep track of when |
|
19
|
|
|
* a key is just not known, or known-but-deleted (=expired) |
|
20
|
|
|
* |
|
21
|
|
|
* @author Matthias Mullie <[email protected]> |
|
22
|
|
|
* @copyright Copyright (c) 2014, Matthias Mullie. All rights reserved |
|
23
|
|
|
* @license LICENSE MIT |
|
24
|
|
|
*/ |
|
25
|
|
|
class Buffer extends MemoryStore |
|
26
|
|
|
{ |
|
27
|
|
|
/** |
|
28
|
|
|
* Make items publicly available - if we create a collection from this, |
|
29
|
|
|
* that collection will need to be able to access these items to determine |
|
30
|
|
|
* if something has expired. |
|
31
|
|
|
* |
|
32
|
|
|
* @var array |
|
33
|
|
|
*/ |
|
34
|
|
|
public $items = array(); |
|
35
|
|
|
|
|
36
|
|
|
/** |
|
37
|
|
|
* Checks if a value exists in cache and is not yet expired. |
|
38
|
|
|
* Contrary to default MemoryStore, expired items must *not* be deleted |
|
39
|
|
|
* from memory: we need to remember that they were expired, so we don't |
|
40
|
|
|
* reach out to real cache (only to get nothing, since it's expired...). |
|
41
|
|
|
* |
|
42
|
|
|
* @param string $key |
|
43
|
|
|
* |
|
44
|
|
|
* @return bool |
|
45
|
|
|
*/ |
|
46
|
|
|
protected function exists($key) |
|
47
|
|
|
{ |
|
48
|
|
|
if (!array_key_exists($key, $this->items)) { |
|
49
|
|
|
// key not in cache |
|
50
|
|
|
return false; |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
|
|
$expire = $this->items[$key][1]; |
|
54
|
|
|
if (0 !== $expire && $expire < time()) { |
|
55
|
|
|
// not permanent & already expired |
|
56
|
|
|
return false; |
|
57
|
|
|
} |
|
58
|
|
|
|
|
59
|
|
|
$this->lru($key); |
|
60
|
|
|
|
|
61
|
|
|
return true; |
|
62
|
|
|
} |
|
63
|
|
|
|
|
64
|
|
|
/** |
|
65
|
|
|
* Check if a key existed in local storage, but is now expired. |
|
66
|
|
|
* |
|
67
|
|
|
* Because our local buffer is also just a real cache, expired items will |
|
68
|
|
|
* just return nothing, which will lead us to believe no such item exists in |
|
69
|
|
|
* that local cache, and we'll reach out to the real cache (where the value |
|
70
|
|
|
* may not yet have been expired because that may have been part of an |
|
71
|
|
|
* uncommitted write) |
|
72
|
|
|
* So we'll want to know when a value is in local cache, but expired! |
|
73
|
|
|
* |
|
74
|
|
|
* @param string $key |
|
75
|
|
|
* |
|
76
|
|
|
* @return bool |
|
77
|
|
|
*/ |
|
78
|
|
|
public function expired($key) |
|
79
|
|
|
{ |
|
80
|
|
|
if (false !== $this->get($key)) { |
|
81
|
|
|
// returned a value, clearly not yet expired |
|
82
|
|
|
return false; |
|
83
|
|
|
} |
|
84
|
|
|
|
|
85
|
|
|
// a known item, not returned by get, is expired |
|
86
|
|
|
return array_key_exists($key, $this->items); |
|
87
|
|
|
} |
|
88
|
|
|
|
|
89
|
|
|
/** |
|
90
|
|
|
* {@inheritdoc} |
|
91
|
|
|
*/ |
|
92
|
|
|
public function getCollection($name) |
|
93
|
|
|
{ |
|
94
|
|
|
return new BufferCollection($this, $name); |
|
95
|
|
|
} |
|
96
|
|
|
} |
|
97
|
|
|
|