29 use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
31 use Psr\Log\LoggerInterface;
36 use Wikimedia\ScopedCallback;
82 StatsdDataFactoryInterface
$stats,
112 $dbw = $this->lb->getConnectionRef(
DB_MASTER );
113 if ( !$dbw->lock( $key, $fname, 0 ) ) {
118 $unlocker =
new ScopedCallback(
function () use ( $dbw, $key, $fname ) {
119 $dbw->unlock( $key, $fname );
126 if ( $editInfo &&
wfTimestamp( TS_UNIX, $editInfo->timestamp ) >= $cutoffTime ) {
127 $alreadyCached =
true;
129 $format =
$content->getDefaultFormat();
131 $editInfo->output->setCacheTime( $editInfo->timestamp );
132 $alreadyCached =
false;
135 $context = [
'cachekey' => $key,
'title' =>
$title->getPrefixedText() ];
137 if ( $editInfo && $editInfo->output ) {
140 [ $page,
$content, $editInfo->output, $summary, $user ] );
142 if ( $alreadyCached ) {
143 $logger->debug(
"Parser output for key '{cachekey}' already cached.",
$context );
150 $editInfo->pstContent,
152 $editInfo->timestamp,
156 if ( $code ===
true ) {
157 $logger->debug(
"Cached parser output for key '{cachekey}'.",
$context );
160 } elseif ( $code ===
'uncacheable' ) {
162 "Uncacheable parser output for key '{cachekey}' [{code}].",
169 "Failed to cache parser output for key '{cachekey}'.",
205 $this->initiator !== self::INITIATOR_USER ||
218 'title' =>
$title->getPrefixedText(),
223 if ( !is_object( $editInfo ) || !$editInfo->output ) {
226 $logger->info(
"Empty cache for key '{key}' but not for user.",
$context );
234 $age = time() - (int)
wfTimestamp( TS_UNIX, $editInfo->output->getCacheTime() );
237 $isCacheUsable =
true;
238 if ( $age <= self::PRESUME_FRESH_TTL_SEC ) {
241 $logger->debug(
"Timestamp-based cache hit for key '{key}'.",
$context );
242 } elseif ( $user->
isAnon() ) {
244 $cacheTime = $editInfo->output->getCacheTime();
245 if ( $lastEdit < $cacheTime ) {
248 $logger->debug(
"Edit check based cache hit for key '{key}'.",
$context );
250 $isCacheUsable =
false;
252 $logger->info(
"Stale cache for key '{key}' due to outside edits.",
$context );
258 $logger->debug(
"Edit count based cache hit for key '{key}'.",
$context );
260 $isCacheUsable =
false;
262 $logger->info(
"Stale cache for key '{key}'due to outside edits.",
$context );
266 if ( !$isCacheUsable ) {
270 if ( $editInfo->output->getFlag(
'vary-revision' ) ) {
274 "Cache for key '{key}' has vary-revision; post-insertion parse inevitable.",
278 static $flagsMaybeReparse = [
282 'vary-revision-timestamp',
284 'vary-revision-sha1',
288 foreach ( $flagsMaybeReparse as $flag ) {
289 if ( $editInfo->output->getFlag( $flag ) ) {
291 "Cache for key '{key}' has $flag; post-insertion parse possible.",
306 $this->stats->increment(
'editstash.' . $subkey );
307 $this->stats->increment(
'editstash_by_model.' .
$content->getModel() .
'.' . $subkey );
318 $start = microtime(
true );
323 $dbw = $this->lb->getAnyOpenConnection( $this->lb->getWriterIndex() );
324 if ( $dbw && $dbw->lock( $key, __METHOD__, 30 ) ) {
326 $dbw->unlock( $key, __METHOD__ );
329 $timeMs = 1000 * max( 0, microtime(
true ) - $start );
330 $this->stats->timing(
'editstash.lock_wait_time', $timeMs );
341 $textKey = $this->cache->makeKey(
'stashedit',
'text', $textHash );
343 return $this->cache->get( $textKey );
352 $textKey = $this->cache->makeKey(
'stashedit',
'text', $textHash );
354 return $this->cache->set(
367 $db = $this->lb->getConnectionRef(
DB_REPLICA );
370 $time = $db->selectField(
371 [
'recentchanges' ] + $actorQuery[
'tables'],
373 [ $actorQuery[
'conds'] ],
389 return sha1( implode(
"\n", [
409 return $this->cache->makeKey(
411 md5(
$title->getPrefixedDBkey() ),
424 $stashInfo = $this->cache->get( $key );
425 if ( is_object( $stashInfo ) && $stashInfo->output instanceof
ParserOutput ) {
456 if ( $parserOutput->
getFlag(
'user-signature' ) ) {
457 $ttl = min( $ttl, self::MAX_SIGNATURE_TTL );
461 return 'uncacheable';
465 $stashInfo = (object)[
466 'pstContent' => $pstContent,
467 'output' => $parserOutput,
468 'timestamp' => $timestamp,
478 return $ok ?
true :
'store_error';
486 $key = $this->cache->makeKey(
'stash-edit-recent', sha1( $user->
getName() ) );
488 $keyList = $this->cache->get( $key ) ?: [];
489 if ( count( $keyList ) >= self::MAX_CACHE_RECENT ) {
490 $oldestKey = array_shift( $keyList );
494 $keyList[] = $newKey;
495 $this->cache->set( $key, $keyList, 2 * self::MAX_CACHE_TTL );
503 $key = $this->cache->makeKey(
'stash-edit-recent', sha1( $user->
getName() ) );
505 return count( $this->cache->get( $key ) ?: [] );