21 use MediaWikiCoversValidator;
22 use PHPUnit4And6Compat;
36 $wanCache = TestingAccessWrapper::newFromObject( $this->
cache );
38 $this->internalCache = $wanCache->cache;
54 $this->
cache->get( $key, $curTTL, [], $asOf );
55 $this->
assertNull( $curTTL,
"Current TTL is null" );
56 $this->
assertNull( $asOf,
"Current as-of-time is infinite" );
96 $this->
assertNull( $curTTL,
"Non-existing key has null current TTL" );
104 for ( $i = 0; $i < 3; ++
$i ) {
120 $this->
assertFalse( $this->
cache->get( $key ),
"Stale set() value ignored" );
124 $mockWallClock = 1549343530.2053;
125 $this->
cache->setMockTime( $mockWallClock );
128 $callback =
function () use ( &$hit ) {
133 $groups = [
'thiscache:1',
'thatcache:1',
'somecache:1' ];
135 foreach (
$keys as $i => $key ) {
136 $this->
cache->getWithSetCallback(
137 $key, 100, $callback, [
'pcTTL' => 5,
'pcGroup' => $groups[$i] ] );
141 foreach (
$keys as $i => $key ) {
142 $this->
cache->getWithSetCallback(
143 $key, 100, $callback, [
'pcTTL' => 5,
'pcGroup' => $groups[$i] ] );
147 foreach (
$keys as $i => $key ) {
148 $this->
cache->getWithSetCallback(
149 "$key-2", 100, $callback, [
'pcTTL' => 5,
'pcGroup' => $groups[$i] ] );
153 foreach (
$keys as $i => $key ) {
154 $this->
cache->getWithSetCallback(
155 "$key-2", 100, $callback, [
'pcTTL' => 5,
'pcGroup' => $groups[$i] ] );
159 foreach (
$keys as $i => $key ) {
161 $this->
cache->delete( $key );
162 $mockWallClock += 0.001;
164 $this->
cache->getWithSetCallback(
165 $key, 100, $callback, [
'pcTTL' => 5,
'pcGroup' => $groups[$i] ] );
167 $this->
assertEquals( 9, $hit,
"Values evicted by delete()" );
170 $key = reset(
$keys );
171 $this->
cache->getWithSetCallback( $key, 100, $callback, [
'pcTTL' => 5 ] );
172 $this->
assertEquals( 9, $hit,
"Value recently interim-cached" );
174 $mockWallClock += 0.2;
175 $this->
cache->clearProcessCache();
176 $this->
cache->getWithSetCallback( $key, 100, $callback, [
'pcTTL' => 5 ] );
177 $this->
assertEquals( 10, $hit,
"Value calculated (interim key not recent and reset)" );
178 $this->
cache->getWithSetCallback( $key, 100, $callback, [
'pcTTL' => 5 ] );
179 $this->
assertEquals( 10, $hit,
"Value process cached" );
181 $mockWallClock += 0.2;
182 $outerCallback =
function () use ( &$callback, $key ) {
183 $v = $this->
cache->getWithSetCallback( $key, 100, $callback, [
'pcTTL' => 5 ] );
188 $this->
cache->getWithSetCallback(
"$key-miss-outer", 100, $outerCallback );
189 $this->
assertEquals( 11, $hit,
"Nested callback value process cache skipped" );
210 $func =
function ( $old, &$ttl, &$opts,
$asOf )
211 use ( &$wasSet, &$priorValue, &$priorAsOf,
$value ) {
219 $mockWallClock = 1549343530.2053;
227 $this->
assertFalse( $priorValue,
"No prior value" );
228 $this->
assertNull( $priorAsOf,
"No prior value" );
237 $key, 30, $func, [
'lowTTL' => 0,
'lockTSE' => 5 ] + $extOpts );
239 $this->
assertEquals( 0, $wasSet,
"Value not regenerated" );
245 $key, 30, $func, [
'checkKeys' => [ $cKey1, $cKey2 ] ] + $extOpts
248 $this->
assertEquals( 1, $wasSet,
"Value regenerated due to check keys" );
256 $mockWallClock += 0.2;
260 $key, 30, $func, [
'checkKeys' => [ $cKey1, $cKey2 ] ] + $extOpts
263 $this->
assertEquals( 1, $wasSet,
"Value regenerated due to still-recent check keys" );
270 $v =
$cache->
get( $key, $curTTL, [ $cKey1, $cKey2 ] );
285 $this->
assertEquals( 1, $wasSet,
"Value process cached while deleted" );
287 $oldValReceived = -1;
288 $oldAsOfReceived = -1;
290 use ( &$oldValReceived, &$oldAsOfReceived, &$wasSet ) {
298 $mockWallClock = 1549343530.2053;
304 $key, 30, $checkFunc, [
'staleTTL' => 50 ] + $extOpts );
306 $this->
assertEquals(
false, $oldValReceived,
"Callback got no stale value" );
307 $this->
assertEquals(
null, $oldAsOfReceived,
"Callback got no stale value" );
309 $mockWallClock += 40;
311 $key, 30, $checkFunc, [
'staleTTL' => 50 ] + $extOpts );
312 $this->
assertEquals(
'xxx2', $v,
"Value still returned after expired" );
313 $this->
assertEquals( 2, $wasSet,
"Value recalculated while expired" );
314 $this->
assertEquals(
'xxx1', $oldValReceived,
"Callback got stale value" );
315 $this->
assertNotEquals(
null, $oldAsOfReceived,
"Callback got stale value" );
317 $mockWallClock += 260;
319 $key, 30, $checkFunc, [
'staleTTL' => 50 ] + $extOpts );
320 $this->
assertEquals(
'xxx3', $v,
"Value still returned after expired" );
321 $this->
assertEquals( 3, $wasSet,
"Value recalculated while expired" );
322 $this->
assertEquals(
false, $oldValReceived,
"Callback got no stale value" );
323 $this->
assertEquals(
null, $oldAsOfReceived,
"Callback got no stale value" );
325 $mockWallClock = ( $priorTime - $cache::HOLDOFF_TTL - 1 );
333 $cache::TTL_INDEFINITE,
335 [
'graceTTL' => $cache::TTL_WEEK,
'checkKeys' => [ $checkKey ] ] + $extOpts
339 $this->
assertEquals(
false, $oldValReceived,
"Callback got no stale value" );
340 $this->
assertEquals(
null, $oldAsOfReceived,
"Callback got no stale value" );
342 $mockWallClock += $cache::TTL_HOUR;
345 $cache::TTL_INDEFINITE,
347 [
'graceTTL' => $cache::TTL_WEEK,
'checkKeys' => [ $checkKey ] ] + $extOpts
349 $this->
assertEquals(
'xxx1', $v,
"Cached value returned" );
350 $this->
assertEquals( 1, $wasSet,
"Cached value returned" );
353 $mockWallClock += 0.01;
357 $cache::TTL_INDEFINITE,
359 [
'graceTTL' => $cache::TTL_WEEK,
'checkKeys' => [ $checkKey ] ] + $extOpts
361 $this->
assertEquals(
'xxx1', $v,
"Value still returned after expired (in grace)" );
362 $this->
assertEquals( 1, $wasSet,
"Value still returned after expired (in grace)" );
365 $mockWallClock += $cache::TTL_WEEK;
368 $cache::TTL_INDEFINITE,
370 [
'graceTTL' => $cache::TTL_WEEK,
'checkKeys' => [ $checkKey ] ] + $extOpts
372 $this->
assertEquals(
'xxx2', $v,
"Value was recomputed (past grace)" );
373 $this->
assertEquals( 2, $wasSet,
"Value was recomputed (past grace)" );
374 $this->
assertEquals(
'xxx1', $oldValReceived,
"Callback got post-grace stale value" );
375 $this->
assertNotEquals(
null, $oldAsOfReceived,
"Callback got post-grace stale value" );
388 $mockWallClock = 1549343530.2053;
401 $touchedCallback =
function () use ( &$touched ) {
406 $cache::TTL_INDEFINITE,
408 [
'touchedCallback' => $touchedCallback ] + $extOpts
410 $mockWallClock += 60;
413 $cache::TTL_INDEFINITE,
415 [
'touchedCallback' => $touchedCallback ] + $extOpts
417 $this->
assertEquals(
'xxx1', $v,
"Value was computed once" );
418 $this->
assertEquals( 1, $wasSet,
"Value was computed once" );
420 $touched = $mockWallClock - 10;
423 $cache::TTL_INDEFINITE,
425 [
'touchedCallback' => $touchedCallback ] + $extOpts
429 $cache::TTL_INDEFINITE,
431 [
'touchedCallback' => $touchedCallback ] + $extOpts
433 $this->
assertEquals(
'xxx2', $v,
"Value was recomputed once" );
434 $this->
assertEquals( 2, $wasSet,
"Value was recomputed once" );
440 [ [
'version' => 1 ],
true ]
447 $func =
function ( $old, &$ttl, &$opts,
$asOf ) use ( &$wasSet, &
$value )
454 $mockWallClock = 1549343530.2053;
459 $opts = [
'lowTTL' => 30 ];
464 $mockWallClock += 0.2;
466 $this->
assertEquals( 2, $wasSet,
"Value re-calculated" );
470 $opts = [
'lowTTL' => 1 ];
478 $asyncHandler =
function ( $callback ) use ( &$asycList ) {
479 $asycList[] = $callback;
483 'asyncHandler' => $asyncHandler
486 $mockWallClock = 1549343530.2053;
492 $opts = [
'lowTTL' => 100 ];
500 $mockWallClock += 250;
504 $this->
assertEquals( 1, count( $asycList ),
"Refresh deferred." );
508 $this->
assertEquals( 2, $wasSet,
"Value calculated at later time" );
509 $this->
assertEquals( 0, count( $asycList ),
"No deferred refreshes added." );
522 $opts = [
'hotTTR' => 900 ];
527 $mockWallClock += 30;
535 $opts = [
'hotTTR' => 10 ];
540 $mockWallClock += 30;
544 $this->
assertEquals( 2, $wasSet,
"Value re-calculated" );
553 $this->
cache->getWithSetCallback(
'key', 30,
'invalid callback' );
576 $genFunc =
function ( $id, $old, &$ttl, &$opts,
$asOf ) use (
577 &$wasSet, &$priorValue, &$priorAsOf
586 $mockWallClock = 1549343530.2053;
594 $keyedIds, 30, $genFunc, [
'lockTSE' => 5 ] + $extOpts );
597 $this->
assertFalse( $priorValue,
"No prior value" );
598 $this->
assertNull( $priorAsOf,
"No prior value" );
609 $keyedIds, 30, $genFunc, [
'lowTTL' => 0,
'lockTSE' => 5, ] + $extOpts );
614 $keyedIds, 30, $genFunc, [
'lowTTL' => 0,
'lockTSE' => 5, ] + $extOpts );
616 $this->
assertEquals( 1, $wasSet,
"Value not regenerated" );
624 $keyedIds, 30, $genFunc, [
'checkKeys' => [ $cKey1, $cKey2 ] ] + $extOpts
627 $this->
assertEquals( 1, $wasSet,
"Value regenerated due to check keys" );
635 $mockWallClock += 0.01;
641 $keyedIds, 30, $genFunc, [
'checkKeys' => [ $cKey1, $cKey2 ] ] + $extOpts
644 $this->
assertEquals( 1, $wasSet,
"Value regenerated due to still-recent check keys" );
651 $v =
$cache->
get( $keyC, $curTTL, [ $cKey1, $cKey2 ] );
663 $keyedIds, 30, $genFunc, [
'pcTTL' => 5 ] + $extOpts );
664 $this->
assertEquals(
"@{$keyedIds[$key]}$", $v[$key],
"Value returned" );
668 $keyedIds, 30, $genFunc, [
'pcTTL' => 5 ] + $extOpts );
669 $this->
assertEquals(
"@{$keyedIds[$key]}$", $v[$key],
"Value still returned after deleted" );
670 $this->
assertEquals( 1, $wasSet,
"Value process cached while deleted" );
673 $ids = [ 1, 2, 3, 4, 5, 6 ];
675 return $wanCache->makeKey(
'test', $id );
686 [
"val-1",
"val-2",
"val-3",
"val-4",
"val-5",
"val-6" ],
688 "Correct values in correct order"
693 "Correct keys in correct order"
698 $this->
assertEquals( count( $ids ), $calls,
"Values cached" );
702 ->setMethods( [
'getMulti' ] )->getMock();
703 $localBag->expects( $this->
exactly( 1 ) )->method(
'getMulti' )->willReturn( [
704 WANObjectCache::VALUE_KEY_PREFIX .
'k1' =>
'val-id1',
705 WANObjectCache::VALUE_KEY_PREFIX .
'k2' =>
'val-id2'
710 $keyedIds =
new ArrayIterator( [
'k1' =>
'id1',
'k2' =>
'id2' ] );
712 [
'k1' =>
'val-id1',
'k2' =>
'val-id2' ],
713 $wanCache->getMultiWithSetCallback( $keyedIds, 10, $genFunc, [
'pcTTL' => 5 ] )
717 [
'k1' =>
'val-id1',
'k2' =>
'val-id2' ],
718 $wanCache->getMultiWithSetCallback( $keyedIds, 10, $genFunc, [
'pcTTL' => 5 ] )
725 [ [
'version' => 1 ],
true ]
747 &$wasSet, &$priorValue, &$priorAsOf
750 foreach ( $ids as $id ) {
752 $newValues[$id] =
"@$id$";
759 $mockWallClock = 1549343530.2053;
767 $keyedIds, 30, $genFunc, $extOpts );
780 $keyedIds, 30, $genFunc, [
'lowTTL' => 0 ] + $extOpts );
785 $keyedIds, 30, $genFunc, [
'lowTTL' => 0 ] + $extOpts );
787 $this->
assertEquals( 1, $wasSet,
"Value not regenerated" );
795 $keyedIds, 30, $genFunc, [
'checkKeys' => [ $cKey1, $cKey2 ] ] + $extOpts
798 $this->
assertEquals( 1, $wasSet,
"Value regenerated due to check keys" );
804 $mockWallClock += 0.01;
810 $keyedIds, 30, $genFunc, [
'checkKeys' => [ $cKey1, $cKey2 ] ] + $extOpts
813 $this->
assertEquals( 1, $wasSet,
"Value regenerated due to still-recent check keys" );
820 $v =
$cache->
get( $keyC, $curTTL, [ $cKey1, $cKey2 ] );
832 $keyedIds, 30, $genFunc, [
'pcTTL' => 5 ] + $extOpts );
833 $this->
assertEquals(
"@{$keyedIds[$key]}$", $v[$key],
"Value returned" );
837 $keyedIds, 30, $genFunc, [
'pcTTL' => 5 ] + $extOpts );
838 $this->
assertEquals(
"@{$keyedIds[$key]}$", $v[$key],
"Value still returned after deleted" );
839 $this->
assertEquals( 1, $wasSet,
"Value process cached while deleted" );
842 $ids = [ 1, 2, 3, 4, 5, 6 ];
844 return $wanCache->makeKey(
'test', $id );
849 foreach ( $ids as $id ) {
851 $newValues[$id] =
"val-{$id}";
859 [
"val-1",
"val-2",
"val-3",
"val-4",
"val-5",
"val-6" ],
861 "Correct values in correct order"
866 "Correct keys in correct order"
871 $this->
assertEquals( count( $ids ), $calls,
"Values cached" );
877 [ [
'version' => 1 ],
true ]
890 $mockWallClock = 1549343530.2053;
894 $func =
function () use ( &$calls,
$value,
$cache, $key ) {
901 $this->
assertEquals( 1, $calls,
'Value was populated' );
904 $this->internalCache->add( $cache::MUTEX_KEY_PREFIX . $key, 1, 0 );
908 [
'lockTSE' => 5,
'checkKeys' => $checkKeys ] );
910 $this->
assertEquals( 1, $calls,
'Callback was not used' );
913 $mockWallClock += 0.001;
915 [
'lockTSE' => 5,
'checkKeys' => $checkKeys ] );
917 $this->
assertEquals( 2, $calls,
'Callback was used; interim saved' );
920 [
'lockTSE' => 5,
'checkKeys' => $checkKeys ] );
922 $this->
assertEquals( 2, $calls,
'Callback was not used; used interim (mutex failed)' );
936 $mockWallClock = 1549343530.2053;
942 $setOpts[
'since'] = $mockWallClock - 10;
951 $this->
assertEquals( 1, $curTTL,
'Value has reduced logical TTL', 0.01 );
952 $this->
assertEquals( 1, $calls,
'Value was generated' );
958 $this->
assertEquals( 2, $calls,
'Callback used (mutex acquired)' );
962 $this->
assertEquals( 2, $calls,
'Callback was not used (interim value used)' );
966 $this->internalCache->add( $cache::MUTEX_KEY_PREFIX . $key, 1, 0 );
970 $this->
assertEquals( 2, $calls,
'Callback was not used (mutex not acquired)' );
972 $mockWallClock += 301;
974 $this->internalCache->add( $cache::MUTEX_KEY_PREFIX . $key, 1, 0 );
978 $this->
assertEquals( 3, $calls,
'Callback was used (mutex not acquired, not in cache)' );
983 $setOpts[
'lag'] = 15;
992 $this->
assertEquals( 30, $curTTL,
'Value has reduced logical TTL', 0.01 );
993 $this->
assertEquals( 1, $calls,
'Value was generated' );
997 $this->
assertEquals( 1, $calls,
'Callback was used (not expired)' );
999 $mockWallClock += 31;
1003 $this->
assertEquals( 2, $calls,
'Callback was used (mutex acquired)' );
1016 $mockWallClock = 1549343530.2053;
1020 $func =
function () use ( &$calls,
$value,
$cache, $key ) {
1027 $this->
assertEquals( 1, $calls,
'Value was populated' );
1029 $mockWallClock += 0.2;
1032 $this->internalCache->add( $cache::MUTEX_KEY_PREFIX . $key, 1, 0 );
1036 [
'busyValue' => $busyValue,
'checkKeys' => $checkKeys ] );
1041 [
'lockTSE' => 30,
'busyValue' => $busyValue,
'checkKeys' => $checkKeys ] );
1043 $this->
assertEquals( 2, $calls,
'Callback was not used' );
1047 [
'busyValue' => $busyValue,
'checkKeys' => $checkKeys ] );
1048 $this->
assertEquals( $busyValue,
$ret,
'Callback was not used; used busy value' );
1049 $this->
assertEquals( 2, $calls,
'Callback was not used; used busy value' );
1051 $this->internalCache->delete( $cache::MUTEX_KEY_PREFIX . $key );
1052 $mockWallClock += 0.001;
1054 [
'lockTSE' => 30,
'busyValue' => $busyValue,
'checkKeys' => $checkKeys ] );
1056 $this->
assertEquals( 3, $calls,
'Callback was used; saved interim' );
1058 $this->internalCache->add( $cache::MUTEX_KEY_PREFIX . $key, 1, 0 );
1060 [
'busyValue' => $busyValue,
'checkKeys' => $checkKeys ] );
1062 $this->
assertEquals( 3, $calls,
'Callback was not used; used interim' );
1071 $value1 = [
'this' =>
'is',
'a' =>
'test' ];
1072 $value2 = [
'this' =>
'is',
'another' =>
'test' ];
1078 $mockWallClock = 1549343530.2053;
1087 [ $key1 => $value1, $key2 => $value2 ],
1089 'Result array populated'
1092 $this->
assertEquals( 2, count( $curTTLs ),
"Two current TTLs in array" );
1099 $mockWallClock += 1;
1103 [ $key1 => $value1, $key2 => $value2 ],
1104 $cache->
getMulti( [ $key1, $key2, $key3 ], $curTTLs, [ $cKey1, $cKey2 ] ),
1105 "Result array populated even with new check keys"
1111 $this->
assertEquals( 2, count( $curTTLs ),
"Current TTLs array set" );
1115 $mockWallClock += 1;
1119 [ $key1 => $value1, $key2 => $value2 ],
1120 $cache->
getMulti( [ $key1, $key2, $key3 ], $curTTLs, [ $cKey1, $cKey2 ] ),
1121 "Result array still populated even with new check keys"
1123 $this->
assertEquals( 2, count( $curTTLs ),
"Current TTLs still array set" );
1124 $this->
assertLessThan( 0, $curTTLs[$key1],
'Key 1 has negative current TTL' );
1125 $this->
assertLessThan( 0, $curTTLs[$key2],
'Key 2 has negative current TTL' );
1142 $mockWallClock = 1549343530.2053;
1147 foreach ( [ $checkAll, $check1, $check2 ] as $checkKey ) {
1151 $mockWallClock += 0.100;
1157 $result =
$cache->
getMulti( [
'key1',
'key2',
'key3' ], $curTTLs, [
1164 [
'key1' => $value1,
'key2' => $value2 ],
1173 $mockWallClock += 0.100;
1177 $result =
$cache->
getMulti( [
'key1',
'key2',
'key3' ], $curTTLs, [
1184 [
'key1' => $value1,
'key2' => $value2 ],
1186 'key1 expired by check1, but value still provided'
1188 $this->
assertLessThan( 0, $curTTLs[
'key1'],
'key1 TTL expired' );
1194 $result =
$cache->
getMulti( [
'key1',
'key2',
'key3' ], $curTTLs, [
1201 [
'key1' => $value1,
'key2' => $value2 ],
1203 'All keys expired by checkAll, but value still provided'
1205 $this->
assertLessThan( 0, $curTTLs[
'key1'],
'key1 expired by checkAll' );
1206 $this->
assertLessThan( 0, $curTTLs[
'key2'],
'key2 expired by checkAll' );
1216 for ( $i = 0; $i < 500; ++
$i ) {
1220 $cache->
get( $key, $curTTL, [ $checkKey ] );
1223 $v =
$cache->
get( $key, $curTTL, [ $checkKey ] );
1226 $this->
assertLessThan( 0, $curTTL,
"Step $i: CTL < 0 (miss/set/hit)" );
1229 for ( $i = 0; $i < 500; ++
$i ) {
1235 $v =
$cache->
get( $key, $curTTL, [ $checkKey ] );
1238 $this->
assertLessThan( 0, $curTTL,
"Step $i: CTL < 0 (set/hit)" );
1253 $v = $this->
cache->get( $key, $curTTL );
1257 $this->
cache->delete( $key );
1260 $v = $this->
cache->get( $key, $curTTL );
1261 $this->
assertFalse( $v,
"Deleted key has false value" );
1262 $this->
assertLessThan( 0, $curTTL,
"Deleted key has current TTL < 0" );
1265 $v = $this->
cache->get( $key, $curTTL );
1266 $this->
assertFalse( $v,
"Deleted key is tombstoned and has false value" );
1267 $this->
assertLessThan( 0, $curTTL,
"Deleted key is tombstoned and has current TTL < 0" );
1270 $this->
cache->delete( $key, WANObjectCache::HOLDOFF_NONE );
1273 $v = $this->
cache->get( $key, $curTTL );
1274 $this->
assertFalse( $v,
"Deleted key has false value" );
1275 $this->
assertNull( $curTTL,
"Deleted key has null current TTL" );
1278 $v = $this->
cache->get( $key, $curTTL );
1298 $funcV1 =
function () use ( &$wasSet, $valueV1 ) {
1304 $priorValue =
false;
1307 use ( &$wasSet, $valueV2, &$priorValue, &$priorAsOf ) {
1319 $this->
assertEquals( 1, $wasSet,
"Value regenerated" );
1321 $this->
assertEquals( 1, $wasSet,
"Value not regenerated" );
1322 $this->
assertEquals( $valueV1, $v,
"Value not regenerated" );
1326 $verOpts = [
'version' => $extOpts[
'version'] + 1 ];
1329 $verOpts = [
'version' => 1 ];
1336 $this->
assertEquals( 1, $wasSet,
"Value regenerated" );
1337 $this->
assertEquals(
false, $priorValue,
"Old value not given due to old format" );
1338 $this->
assertEquals(
null, $priorAsOf,
"Old value not given due to old format" );
1342 $this->
assertEquals( $valueV2, $v,
"Value not regenerated (secondary key)" );
1343 $this->
assertEquals( 0, $wasSet,
"Value not regenerated (secondary key)" );
1352 $this->
assertEquals( 1, $wasSet,
"Value regenerated" );
1355 $this->
assertEquals( $valueV2, $v,
"Value not regenerated (main key)" );
1356 $this->
assertEquals( 1, $wasSet,
"Value not regenerated (main key)" );
1362 [ [
'version' => 1 ],
true ]
1373 $mockWallClock = 1549343530.2053;
1378 $func =
function () use ( &$wasCalled,
$value ) {
1392 $mockWallClock += 0.001;
1394 $this->
assertEquals( 2, $wasCalled,
'Value regenerated (got mutex)' );
1396 $this->
assertEquals( 2, $wasCalled,
'Value interim cached' );
1398 $mockWallClock += 0.2;
1400 $this->
assertEquals( 3, $wasCalled,
'Value regenerated (got mutex)' );
1402 $this->internalCache->add( $cache::MUTEX_KEY_PREFIX . $key, 1, 0 );
1404 $this->
assertEquals( 3, $wasCalled,
'Value interim cached (failed mutex)' );
1405 $this->internalCache->delete( $cache::MUTEX_KEY_PREFIX . $key );
1416 $this->
assertEquals( 2, $wasCalled,
'Value regenerated (got mutex)' );
1418 $this->
assertEquals( 3, $wasCalled,
'Value still regenerated (got mutex)' );
1420 $this->
assertEquals( 4, $wasCalled,
'Value still regenerated (got mutex)' );
1422 $this->internalCache->add( $cache::MUTEX_KEY_PREFIX . $key, 1, 0 );
1424 $this->
assertEquals( 5, $wasCalled,
'Value still regenerated (failed mutex)' );
1439 $mockWallClock = 1549343530.2053;
1443 $mockWallClock += 0.100;
1448 $mockWallClock += 0.100;
1454 $this->
assertEquals( $t1, $t2,
'Check key time did not change' );
1456 $mockWallClock += 0.100;
1462 $this->
assertEquals( $t3, $t4,
'Check key time did not change' );
1464 $mockWallClock += 0.100;
1470 $this->
assertEquals( $t5, $t6,
'Check key time did not change' );
1482 $mockWallClock = 1549343530.2053;
1484 $this->
cache->setMockTime( $mockWallClock );
1487 $this->internalCache->set(
1488 WANObjectCache::TIME_KEY_PREFIX . $tKey2,
1489 WANObjectCache::PURGE_VAL_PREFIX . ( $priorTime - 3 )
1491 $this->internalCache->set(
1492 WANObjectCache::TIME_KEY_PREFIX . $tKey2,
1493 WANObjectCache::PURGE_VAL_PREFIX . ( $priorTime - 5 )
1495 $this->internalCache->set(
1496 WANObjectCache::TIME_KEY_PREFIX . $tKey1,
1497 WANObjectCache::PURGE_VAL_PREFIX . ( $priorTime - 30 )
1502 $v = $this->
cache->get( $key, $curTTL, [ $tKey1, $tKey2 ] );
1519 $knownPurge = time() - 60;
1523 $this->internalCache->set(
1524 WANObjectCache::VALUE_KEY_PREFIX . $vKey1,
1526 WANObjectCache::FLD_VERSION => WANObjectCache::VERSION,
1527 WANObjectCache::FLD_VALUE =>
$value,
1528 WANObjectCache::FLD_TTL => 3600,
1529 WANObjectCache::FLD_TIME => $goodTime
1532 $this->internalCache->set(
1533 WANObjectCache::VALUE_KEY_PREFIX . $vKey2,
1535 WANObjectCache::FLD_VERSION => WANObjectCache::VERSION,
1536 WANObjectCache::FLD_VALUE =>
$value,
1537 WANObjectCache::FLD_TTL => 3600,
1538 WANObjectCache::FLD_TIME => $badTime
1541 $this->internalCache->set(
1542 WANObjectCache::TIME_KEY_PREFIX . $tKey1,
1543 WANObjectCache::PURGE_VAL_PREFIX . $goodTime
1545 $this->internalCache->set(
1546 WANObjectCache::TIME_KEY_PREFIX . $tKey2,
1547 WANObjectCache::PURGE_VAL_PREFIX . $badTime
1552 $this->
cache->reap( $vKey1, $knownPurge, $bad1 );
1553 $this->
cache->reap( $vKey2, $knownPurge, $bad2 );
1558 $this->
cache->reapCheckKey( $tKey1, $knownPurge, $tBad1 );
1559 $this->
cache->reapCheckKey( $tKey2, $knownPurge, $tBad2 );
1569 ->setMethods( [
'get',
'changeTTL' ] )->getMock();
1570 $backend->expects( $this->
once() )->method(
'get' )
1572 WANObjectCache::FLD_VERSION => WANObjectCache::VERSION,
1573 WANObjectCache::FLD_VALUE =>
'value',
1574 WANObjectCache::FLD_TTL => 3600,
1575 WANObjectCache::FLD_TIME => 300,
1577 $backend->expects( $this->
once() )->method(
'changeTTL' )
1578 ->willReturn(
false );
1585 $ret = $wanCache->reap(
'key', 360, $isStale );
1586 $this->
assertTrue( $isStale,
'value was stale' );
1597 $opts = [
'lag' => 300,
'since' =>
microtime(
true ) ];
1602 $opts = [
'lag' => 0,
'since' =>
microtime(
true ) - 300 ];
1604 $this->
assertEquals(
false, $this->
cache->get( $key ),
"Trx-lagged value not written." );
1607 $opts = [
'lag' => 5,
'since' =>
microtime(
true ) - 5 ];
1609 $this->
assertEquals(
false, $this->
cache->get( $key ),
"Lagged value not written." );
1619 $opts = [
'pending' =>
true ];
1621 $this->
assertEquals(
false, $this->
cache->get( $key ),
"Pending value not written." );
1626 ->setMethods( [
'set',
'delete' ] )->getMock();
1627 $localBag->expects( $this->never() )->method(
'set' );
1628 $localBag->expects( $this->never() )->method(
'delete' );
1630 'cache' => $localBag,
1631 'mcrouterAware' =>
true,
1632 'region' =>
'pmtpa',
1633 'cluster' =>
'mw-wan'
1635 $valFunc =
function () {
1640 $wanCache->get(
'x' );
1641 $wanCache->get(
'x', $ctl, [
'check1' ] );
1642 $wanCache->getMulti( [
'x',
'y' ] );
1643 $wanCache->getMulti( [
'x',
'y' ], $ctls, [
'check2' ] );
1644 $wanCache->getWithSetCallback(
'p', 30, $valFunc );
1645 $wanCache->getCheckKeyTime(
'zzz' );
1646 $wanCache->reap(
'x', time() - 300 );
1647 $wanCache->reap(
'zzz', time() - 300 );
1652 ->setMethods( [
'set' ] )->getMock();
1654 'cache' => $localBag,
1655 'mcrouterAware' =>
true,
1656 'region' =>
'pmtpa',
1657 'cluster' =>
'mw-wan'
1660 $localBag->expects( $this->
once() )->method(
'set' )
1661 ->with(
"/*/mw-wan/" . $wanCache::VALUE_KEY_PREFIX .
"test" );
1663 $wanCache->delete(
'test' );
1668 ->setMethods( [
'set' ] )->getMock();
1670 'cache' => $localBag,
1671 'mcrouterAware' =>
true,
1672 'region' =>
'pmtpa',
1673 'cluster' =>
'mw-wan'
1676 $localBag->expects( $this->
once() )->method(
'set' )
1677 ->with(
"/*/mw-wan/" . $wanCache::TIME_KEY_PREFIX .
"test" );
1679 $wanCache->touchCheckKey(
'test' );
1684 ->setMethods( [
'delete' ] )->getMock();
1686 'cache' => $localBag,
1687 'mcrouterAware' =>
true,
1688 'region' =>
'pmtpa',
1689 'cluster' =>
'mw-wan'
1692 $localBag->expects( $this->
once() )->method(
'delete' )
1693 ->with(
"/*/mw-wan/" . $wanCache::TIME_KEY_PREFIX .
"test" );
1695 $wanCache->resetCheckKey(
'test' );
1706 $cache->
set( $key,
'Do what thou Wilt' );
1716 'epoch' => $now - 3600
1726 'epoch' => $now + 3600
1744 $mtime = $ago ? time() -
$ago :
$ago;
1746 $ttl = $this->
cache->adaptiveTTL( $mtime, $maxTTL, $minTTL, $factor );
1751 $ttl = $this->
cache->adaptiveTTL( (
string)$mtime, $maxTTL, $minTTL, $factor );
1759 [ 3600, 900, 30, 0.2, 720 ],
1760 [ 3600, 500, 30, 0.2, 500 ],
1761 [ 3600, 86400, 800, 0.2, 800 ],
1762 [
false, 86400, 800, 0.2, 800 ],
1763 [
null, 86400, 800, 0.2, 800 ]
1773 WANObjectCache::class,
1774 WANObjectCache::newEmpty()
1782 $this->
assertSame(
null, $this->
cache->setLogger(
new Psr\Log\NullLogger ) );
1790 ->setMethods( [
'getQoS' ] )->getMock();
1791 $backend->expects( $this->
once() )->method(
'getQoS' )
1792 ->willReturn( BagOStuff::QOS_UNKNOWN );
1796 $wanCache::QOS_UNKNOWN,
1797 $wanCache->getQoS( $wanCache::ATTR_EMULATION )
1806 ->setMethods( [
'makeKey' ] )->getMock();
1807 $backend->expects( $this->
once() )->method(
'makeKey' )
1808 ->willReturn(
'special' );
1814 $this->
assertSame(
'special', $wanCache->makeKey(
'a',
'b' ) );
1822 ->setMethods( [
'makeGlobalKey' ] )->getMock();
1823 $backend->expects( $this->
once() )->method(
'makeGlobalKey' )
1824 ->willReturn(
'special' );
1830 $this->
assertSame(
'special', $wanCache->makeGlobalKey(
'a',
'b' ) );
1835 [
'domain:page:5',
'page' ],
1836 [
'domain:main-key',
'main-key' ],
1837 [
'domain:page:history',
'page' ],
1838 [
'missingdomainkey',
'missingdomainkey' ]
1847 $wanCache = TestingAccessWrapper::newFromObject(
new WANObjectCache( [
1851 $this->
assertEquals( $class, $wanCache->determineKeyClassForStats( $key ) );
1859 return ( $curTTL > 0 && ( $curTTL + self::CLOCK_SKEW ) < $lowTTL );
1865 return ( ( $now - $asOf ) > $timeTillRefresh );
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two and(2) offer you this license which gives you legal permission to copy
wfRandomString( $length=32)
Get a random string containing a number of pseudo-random hex characters.
Class representing a cache/ephemeral data store.
Simple store for keeping values in an associative array for the current process.
worthRefreshExpiring( $curTTL, $lowTTL)
Check if a key is nearing expiration and thus due for randomized regeneration.
worthRefreshPopular( $asOf, $ageNew, $timeTillRefresh, $now)
Check if a key is due for randomized regeneration due to its popularity.
WANObjectCache::wrap WANObjectCache::unwrap WANObjectCache::worthRefreshExpiring WANObjectCache::wort...
testGetWithSetCallback_versions(array $extOpts, $versioned)
getWithSetCallback_versions_provider WANObjectCache::getWithSetCallback() WANObjectCache::doGetWithSe...
testNewEmpty()
WANObjectCache::__construct WANObjectCache::newEmpty.
testBusyValue()
WANObjectCache::getWithSetCallback() WANObjectCache::doGetWithSetCallback()
testGetWithSetCallback(array $extOpts, $versioned)
getWithSetCallback_provider WANObjectCache::getWithSetCallback() WANObjectCache::doGetWithSetCallback...
testGetWithSetcallback_touched(array $extOpts, $versioned)
getWithSetCallback_provider WANObjectCache::getWithSetCallback() WANObjectCache::doGetWithSetCallback...
testDelete()
WANObjectCache::delete WANObjectCache::relayDelete WANObjectCache::relayPurge.
testSetAndGet( $value, $ttl)
provideSetAndGet WANObjectCache::set() WANObjectCache::get() WANObjectCache::makeKey()
testGetQoS()
WANObjectCache::getQoS.
testReap_fail()
WANObjectCache::reap()
testLockTSESlow()
WANObjectCache::getWithSetCallback() WANObjectCache::doGetWithSetCallback() WANObjectCache::set()
testMakeKey()
WANObjectCache::makeKey.
testGetWithSeveralCheckKeys()
WANObjectCache::getMulti()
testMcRouterSupportBroadcastDelete()
static statsKeyProvider()
testSetOver()
WANObjectCache::set()
testAdaptiveTTL( $ago, $maxTTL, $minTTL, $factor, $adaptiveTTL)
provideAdaptiveTTL WANObjectCache::adaptiveTTL()
testGetMulti()
WANObjectCache::getMulti()
testGetNotExists()
WANObjectCache::get() WANObjectCache::makeGlobalKey()
testReap()
WANObjectCache::reap() WANObjectCache::reapCheckKey()
testGetMultiCheckKeys()
WANObjectCache::getMulti() WANObjectCache::processCheckKeys()
testTouchKeys()
WANObjectCache::touchCheckKey WANObjectCache::resetCheckKey WANObjectCache::getCheckKeyTime WANObject...
testMakeGlobalKey()
WANObjectCache::makeGlobalKey.
static getMultiWithUnionSetCallback_provider()
testSetWithLag()
WANObjectCache::set()
static getMultiWithSetCallback_provider()
testSetLogger()
WANObjectCache::setLogger.
testMcRouterSupportBroadcastTouchCK()
testCheckKeyInitHoldoff()
WANObjectCache::get() WANObjectCache::processCheckKeys()
static getWithSetCallback_versions_provider()
static getWithSetCallback_provider()
testWritePending()
WANObjectCache::set()
testGetMultiWithUnionSetCallback(array $extOpts, $versioned)
getMultiWithUnionSetCallback_provider WANObjectCache::getMultiWithUnionSetCallback() WANObjectCache::...
testMcRouterSupportBroadcastResetCK()
testStaleSet()
WANObjectCache::set()
testGetMultiWithSetCallback(array $extOpts, $versioned)
getMultiWithSetCallback_provider WANObjectCache::getMultiWithSetCallback WANObjectCache::makeMultiKey...
static provideAdaptiveTTL()
static provideSetAndGet()
testStatsKeyClass( $key, $class)
statsKeyProvider WANObjectCache::determineKeyClassForStats
testInterimHoldOffCaching()
WANObjectCache::useInterimHoldOffCaching WANObjectCache::getInterimValue.
testGetWithSetCallback_invalidCallback()
WANObjectCache::getWithSetCallback() WANObjectCache::doGetWithSetCallback()
testLockTSE()
WANObjectCache::getWithSetCallback() WANObjectCache::doGetWithSetCallback()
Multi-datacenter aware caching interface.
touchCheckKey( $key, $holdoff=self::HOLDOFF_TTL)
Purge a "check" key from all datacenters, invalidating keys that use it.
getMulti(array $keys, &$curTTLs=[], array $checkKeys=[], &$info=null)
Fetch the value of several keys from cache.
delete( $key, $ttl=self::HOLDOFF_TTL)
Purge a key from all datacenters.
getCheckKeyTime( $key)
Fetch the value of a timestamp "check" key.
getMultiWithUnionSetCallback(ArrayIterator $keyedIds, $ttl, callable $callback, array $opts=[])
Method to fetch/regenerate multiple cache keys at once.
getMultiWithSetCallback(ArrayIterator $keyedIds, $ttl, callable $callback, array $opts=[])
Method to fetch multiple cache keys at once with regeneration.
getWithSetCallback( $key, $ttl, $callback, array $opts=[])
Method to fetch/regenerate cache keys.
makeMultiKeys(array $entities, callable $keyFunc)
useInterimHoldOffCaching( $enabled)
Enable or disable the use of brief caching for tombstoned keys.
set( $key, $value, $ttl=self::TTL_INDEFINITE, array $opts=[])
Set the value of a key in cache.
makeKey( $class, $component=null)
get( $key, &$curTTL=null, array $checkKeys=[], &$info=null)
Fetch the value of a key from cache.
resetCheckKey( $key)
Delete a "check" key from all datacenters, invalidating keys that use it.
makeGlobalKey( $class, $component=null)
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return true
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
processing should stop and the error should be shown to the user * false
globals will be eliminated from MediaWiki replaced by an application object which would be passed to constructors Whether that would be an convenient solution remains to be but certainly PHP makes such object oriented programming models easier than they were in previous versions For the time being MediaWiki programmers will have to work in an environment with some global context At the time of globals were initialised on startup by MediaWiki of these were configuration which are documented in DefaultSettings php There is no comprehensive documentation for the remaining however some of the most important ones are listed below They are typically initialised either in index php or in Setup php $wgTitle Title object created from the request URL $wgOut OutputPage object for HTTP response $wgUser User object for the user associated with the current request $wgLang Language object selected by user preferences $wgContLang Language object associated with the wiki being viewed $wgParser Parser object Parser extensions register their hooks here $wgRequest WebRequest object
you have access to all of the normal MediaWiki so you can get a DB use the cache
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))