21use Wikimedia\ObjectFactory\ObjectFactory;
42 private $consistencyWindow;
44 private $lastKeyWrites = [];
47 private const MAX_WRITE_DELAY = 5;
65 if ( !isset(
$params[
'writeFactory'] ) ) {
66 throw new InvalidArgumentException(
67 __METHOD__ .
': the "writeFactory" parameter is required' );
68 } elseif ( !isset(
$params[
'readFactory'] ) ) {
69 throw new InvalidArgumentException(
70 __METHOD__ .
': the "readFactory" parameter is required' );
73 $this->consistencyWindow =
$params[
'sessionConsistencyWindow'] ?? self::MAX_WRITE_DELAY;
76 : ObjectFactory::getObjectFromSpec(
$params[
'writeFactory'] );
79 : ObjectFactory::getObjectFromSpec(
$params[
'readFactory'] );
80 $this->attrMap = $this->
mergeFlagMaps( [ $this->readStore, $this->writeStore ] );
83 public function get( $key, $flags = 0 ) {
85 $this->hadRecentSessionWrite( [ $key ] ) ||
93 return $store->proxyCall(
102 public function set( $key, $value, $exptime = 0, $flags = 0 ) {
103 $this->remarkRecentSessionWrite( [ $key ] );
105 return $this->writeStore->proxyCall(
114 public function delete( $key, $flags = 0 ) {
115 $this->remarkRecentSessionWrite( [ $key ] );
117 return $this->writeStore->proxyCall(
126 public function add( $key, $value, $exptime = 0, $flags = 0 ) {
127 $this->remarkRecentSessionWrite( [ $key ] );
129 return $this->writeStore->proxyCall(
138 public function merge( $key, callable $callback, $exptime = 0, $attempts = 10, $flags = 0 ) {
139 $this->remarkRecentSessionWrite( [ $key ] );
141 return $this->writeStore->proxyCall(
150 public function changeTTL( $key, $exptime = 0, $flags = 0 ) {
151 $this->remarkRecentSessionWrite( [ $key ] );
153 return $this->writeStore->proxyCall(
162 public function lock( $key, $timeout = 6, $exptime = 6, $rclass =
'' ) {
163 return $this->writeStore->proxyCall(
173 return $this->writeStore->proxyCall(
184 callable $progress =
null,
188 return $this->writeStore->proxyCall(
197 public function getMulti( array $keys, $flags = 0 ) {
199 $this->hadRecentSessionWrite( $keys ) ||
207 return $store->proxyCall(
216 public function setMulti( array $valueByKey, $exptime = 0, $flags = 0 ) {
217 $this->remarkRecentSessionWrite( array_keys( $valueByKey ) );
219 return $this->writeStore->proxyCall(
229 $this->remarkRecentSessionWrite( $keys );
231 return $this->writeStore->proxyCall(
241 $this->remarkRecentSessionWrite( $keys );
243 return $this->writeStore->proxyCall(
252 public function incrWithInit( $key, $exptime, $step = 1, $init =
null, $flags = 0 ) {
253 $this->remarkRecentSessionWrite( [ $key ] );
255 return $this->writeStore->proxyCall(
265 parent::setMockTime( $time );
266 $this->writeStore->setMockTime( $time );
267 $this->readStore->setMockTime( $time );
274 private function hadRecentSessionWrite( array $keys ) {
276 foreach ( $keys as $key ) {
277 $ts = $this->lastKeyWrites[$key] ?? 0;
278 if ( $ts && ( $now - $ts ) <= $this->consistencyWindow ) {
289 private function remarkRecentSessionWrite( array $keys ) {
291 foreach ( $keys as $key ) {
293 unset( $this->lastKeyWrites[$key] );
294 $this->lastKeyWrites[$key] = $now;
297 if ( ( $now - reset( $this->lastKeyWrites ) ) > $this->consistencyWindow ) {
298 $this->lastKeyWrites = array_filter(
299 $this->lastKeyWrites,
300 function ( $timestamp ) use ( $now ) {
301 return ( ( $now - $timestamp ) <= $this->consistencyWindow );
array $params
The job parameters.
Class representing a cache/ephemeral data store.
mergeFlagMaps(array $bags)
Merge the flag maps of one or more BagOStuff objects into a "lowest common denominator" map.
fieldHasFlags( $field, $flags)
A cache class that directs writes to one set of servers and reads to another.
add( $key, $value, $exptime=0, $flags=0)
Insert an item if it does not already exist.
deleteObjectsExpiringBefore( $timestamp, callable $progress=null, $limit=INF, string $tag=null)
Delete all objects expiring before a certain date.
__construct( $params)
Constructor.
changeTTLMulti(array $keys, $exptime, $flags=0)
Change the expiration of multiple items.
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.
lock( $key, $timeout=6, $exptime=6, $rclass='')
Acquire an advisory lock on a key string, exclusive to the caller.
deleteMulti(array $keys, $flags=0)
Delete a batch of items.
getMulti(array $keys, $flags=0)
Get a batch of items.
changeTTL( $key, $exptime=0, $flags=0)
Change the expiration on an item.
setMulti(array $valueByKey, $exptime=0, $flags=0)
Set a batch of items.
merge( $key, callable $callback, $exptime=0, $attempts=10, $flags=0)
Merge changes into the existing cache value (possibly creating a new one)
unlock( $key)
Release an advisory lock on a key string.