22 use Psr\Log\LoggerAwareInterface;
23 use Psr\Log\LoggerInterface;
24 use Psr\Log\NullLogger;
25 use Wikimedia\ScopedCallback;
79 callable $logCallback,
80 callable $keyCallback,
86 $this->logChunkCallback = $logCallback;
87 $this->keyListCallback = $keyCallback;
88 if ( isset( $params[
'channel'] ) ) {
89 $this->channel = $params[
'channel'];
91 throw new UnexpectedValueException(
"No channel specified." );
94 $this->initialStartWindow = $params[
'initialStartWindow'] ?? 3600;
95 $this->logger = $params[
'logger'] ??
new NullLogger();
108 final public function invoke( $n = 100 ) {
109 $posKey = $this->store->makeGlobalKey(
'WANCache',
'reaper', $this->channel );
110 $scopeLock = $this->store->getScopedLock(
"$posKey:busy", 0 );
116 $status = $this->store->get( $posKey );
122 $events = call_user_func_array(
123 $this->logChunkCallback,
124 [
$status[
'pos'],
$status[
'id'], $now - WANObjectCache::HOLDOFF_TTL - 1, $n ]
129 foreach ( $events as $event ) {
130 $keys = call_user_func_array(
131 $this->keyListCallback,
132 [ $this->cache, $event[
'item'] ]
134 foreach (
$keys as $key ) {
135 unset( $keyEvents[$key] );
137 'pos' => $event[
'pos'],
145 foreach ( $keyEvents as $key => $keyEvent ) {
146 if ( !$this->cache->reap( $key, $keyEvent[
'pos'] ) ) {
150 $lastOkEvent = $event;
153 if ( $lastOkEvent ) {
154 $ok = $this->store->merge(
156 function ( $bag, $key, $curValue ) use ( $lastOkEvent ) {
160 $curCoord = [ $curValue[
'pos'], $curValue[
'id'] ];
161 $newCoord = [ $lastOkEvent[
'pos'], $lastOkEvent[
'id'] ];
162 if ( $newCoord < $curCoord ) {
169 'pos' => $lastOkEvent[
'pos'],
170 'id' => $lastOkEvent[
'id'],
171 'ctime' => $curValue ? $curValue[
'ctime'] : date(
'c' )
177 $pos = $lastOkEvent[
'pos'];
178 $id = $lastOkEvent[
'id'];
180 $this->logger->info(
"Updated cache reap position ($pos, $id)." );
182 $this->logger->error(
"Could not update cache reap position ($pos, $id)." );
186 ScopedCallback::consume( $scopeLock );
195 $posKey = $this->store->makeGlobalKey(
'WANCache',
'reaper', $this->channel );
197 return $this->store->get( $posKey );