MediaWiki master
CachedBagOStuff.php
Go to the documentation of this file.
1<?php
7
8use LogicException;
9
25 protected $store;
27 protected $procCache;
28
34 protected ?bool $wasLastGetCached = null;
35
42 public function __construct( BagOStuff $backend, $params = [] ) {
43 $params['keyspace'] = $backend->keyspace;
44 parent::__construct( $params );
45
46 $this->store = $backend;
47 $this->procCache = new HashBagOStuff( $params );
48
49 $this->attrMap = $backend->attrMap;
50 }
51
53 public function get( $key, $flags = 0 ) {
54 $value = $this->procCache->get( $key, $flags );
55 if ( $value !== false || $this->procCache->hasKey( $key ) ) {
56 $this->wasLastGetCached = true;
57 return $value;
58 }
59
60 $value = $this->store->proxyCall(
61 __FUNCTION__,
62 self::ARG0_KEY,
63 self::RES_NONKEY,
64 func_get_args(),
65 $this
66 );
67 $this->set( $key, $value, self::TTL_INDEFINITE, self::WRITE_CACHE_ONLY );
68
69 $this->wasLastGetCached = false;
70 return $value;
71 }
72
74 public function getMulti( array $keys, $flags = 0 ) {
75 $this->wasLastGetCached = null;
76 $valueByKeyCached = [];
77
78 $keysFetch = [];
79 foreach ( $keys as $key ) {
80 $value = $this->procCache->get( $key, $flags );
81 if ( $value === false && !$this->procCache->hasKey( $key ) ) {
82 $keysFetch[] = $key;
83 } else {
84 $valueByKeyCached[$key] = $value;
85 }
86 }
87
88 $valueByKeyFetched = $this->store->proxyCall(
89 __FUNCTION__,
90 self::ARG0_KEYARR,
91 self::RES_KEYMAP,
92 [ $keysFetch, $flags ],
93 $this
94 );
95 $this->setMulti( $valueByKeyFetched, self::TTL_INDEFINITE, self::WRITE_CACHE_ONLY );
96
97 return $valueByKeyCached + $valueByKeyFetched;
98 }
99
101 public function set( $key, $value, $exptime = 0, $flags = 0 ) {
102 $this->procCache->set( $key, $value, $exptime, $flags );
103
104 if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) {
105 return true;
106 }
107
108 return $this->store->proxyCall(
109 __FUNCTION__,
110 self::ARG0_KEY,
111 self::RES_NONKEY,
112 func_get_args(),
113 $this
114 );
115 }
116
118 public function delete( $key, $flags = 0 ) {
119 $this->procCache->delete( $key, $flags );
120
121 if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) {
122 return true;
123 }
124
125 return $this->store->proxyCall(
126 __FUNCTION__,
127 self::ARG0_KEY,
128 self::RES_NONKEY,
129 func_get_args(),
130 $this
131 );
132 }
133
135 public function add( $key, $value, $exptime = 0, $flags = 0 ) {
136 if ( $this->get( $key ) === false ) {
137 return $this->set( $key, $value, $exptime, $flags );
138 }
139
140 // key already set
141 return false;
142 }
143
144 // These just call the backend (tested elsewhere)
145 // @codeCoverageIgnoreStart
146
148 public function merge( $key, callable $callback, $exptime = 0, $attempts = 10, $flags = 0 ) {
149 $this->procCache->delete( $key );
150
151 return $this->store->proxyCall(
152 __FUNCTION__,
153 self::ARG0_KEY,
154 self::RES_NONKEY,
155 func_get_args(),
156 $this
157 );
158 }
159
161 public function changeTTL( $key, $exptime = 0, $flags = 0 ) {
162 $this->procCache->delete( $key );
163
164 return $this->store->proxyCall(
165 __FUNCTION__,
166 self::ARG0_KEY,
167 self::RES_NONKEY,
168 func_get_args(),
169 $this
170 );
171 }
172
174 public function lock( $key, $timeout = 6, $exptime = 6, $rclass = '' ) {
175 return $this->store->proxyCall(
176 __FUNCTION__,
177 self::ARG0_KEY,
178 self::RES_NONKEY,
179 func_get_args(),
180 $this
181 );
182 }
183
185 public function unlock( $key ) {
186 return $this->store->proxyCall(
187 __FUNCTION__,
188 self::ARG0_KEY,
189 self::RES_NONKEY,
190 func_get_args(),
191 $this
192 );
193 }
194
197 $timestamp,
198 ?callable $progress = null,
199 $limit = INF,
200 ?string $tag = null
201 ) {
202 $this->procCache->deleteObjectsExpiringBefore( $timestamp, $progress, $limit, $tag );
203
204 return $this->store->proxyCall(
205 __FUNCTION__,
206 self::ARG0_NONKEY,
207 self::RES_NONKEY,
208 func_get_args(),
209 $this
210 );
211 }
212
214 public function setMulti( array $valueByKey, $exptime = 0, $flags = 0 ) {
215 $this->procCache->setMulti( $valueByKey, $exptime, $flags );
216
217 if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) {
218 return true;
219 }
220
221 return $this->store->proxyCall(
222 __FUNCTION__,
223 self::ARG0_KEYMAP,
224 self::RES_NONKEY,
225 func_get_args(),
226 $this
227 );
228 }
229
231 public function deleteMulti( array $keys, $flags = 0 ) {
232 $this->procCache->deleteMulti( $keys, $flags );
233
234 if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) {
235 return true;
236 }
237
238 return $this->store->proxyCall(
239 __FUNCTION__,
240 self::ARG0_KEYARR,
241 self::RES_NONKEY,
242 func_get_args(),
243 $this
244 );
245 }
246
248 public function changeTTLMulti( array $keys, $exptime, $flags = 0 ) {
249 $this->procCache->changeTTLMulti( $keys, $exptime, $flags );
250
251 if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) {
252 return true;
253 }
254
255 return $this->store->proxyCall(
256 __FUNCTION__,
257 self::ARG0_KEYARR,
258 self::RES_NONKEY,
259 func_get_args(),
260 $this
261 );
262 }
263
265 public function incrWithInit( $key, $exptime, $step = 1, $init = null, $flags = 0 ) {
266 $this->procCache->delete( $key );
267
268 return $this->store->proxyCall(
269 __FUNCTION__,
270 self::ARG0_KEY,
271 self::RES_NONKEY,
272 func_get_args(),
273 $this
274 );
275 }
276
278 public function setMockTime( &$time ) {
279 parent::setMockTime( $time );
280 $this->procCache->setMockTime( $time );
281 $this->store->setMockTime( $time );
282 }
283
290 public function wasLastGetCached(): bool {
291 if ( $this->wasLastGetCached === null ) {
292 throw new LogicException( __METHOD__ . ' must be called immediately after get()' );
293 }
294
295 $status = $this->wasLastGetCached;
296 // Disallow multiple calls without a get() in between as we expect this method to
297 // be used right after a get().
298 $this->wasLastGetCached = null;
299
300 return $status;
301 }
302
303 // @codeCoverageIgnoreEnd
304}
305
307class_alias( CachedBagOStuff::class, 'CachedBagOStuff' );
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:68
Abstract class for any ephemeral data store.
Definition BagOStuff.php:73
get( $key, $flags=0)
Get an item.
const WRITE_CACHE_ONLY
Bitfield constants for set()/merge(); these are only advisory.
Wrap any BagOStuff and add an in-process memory cache to it.
setMulti(array $valueByKey, $exptime=0, $flags=0)
Set a batch of items.This does not support WRITE_ALLOW_SEGMENTS to avoid excessive read I/OWRITE_BACK...
bool $wasLastGetCached
Whether the last get() call was read from cache ($procCache) or the actual store.
changeTTL( $key, $exptime=0, $flags=0)
Change the expiration on an item.If an expiry in the past is given then the key will immediately be e...
lock( $key, $timeout=6, $exptime=6, $rclass='')
Acquire an advisory lock on a key string, exclusive to the caller.bool Success
unlock( $key)
Release an advisory lock on a key string.bool Success
deleteMulti(array $keys, $flags=0)
Delete a batch of items.This does not support WRITE_ALLOW_SEGMENTS to avoid excessive read I/OWRITE_B...
incrWithInit( $key, $exptime, $step=1, $init=null, $flags=0)
Increase the value of the given key (no TTL change) if it exists or create it otherwise....
deleteObjectsExpiringBefore( $timestamp, ?callable $progress=null, $limit=INF, ?string $tag=null)
Delete all objects expiring before a certain date.bool Success; false if unimplemented
merge( $key, callable $callback, $exptime=0, $attempts=10, $flags=0)
Merge changes into the existing cache value (possibly creating a new one)The callback function return...
getMulti(array $keys, $flags=0)
Get a batch of items.mixed[] Map of (key => value) for existing keys
add( $key, $value, $exptime=0, $flags=0)
Insert an item if it does not already exist.bool Success (item created)
wasLastGetCached()
True if the last get() call was read from cache, false if it was a cache miss.
changeTTLMulti(array $keys, $exptime, $flags=0)
Change the expiration of multiple items.BagOStuff::changeTTL()bool Success (all items found and updat...
__construct(BagOStuff $backend, $params=[])
Store data in a memory for the current request/process only.