Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
LocalCache
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 4
110
0.00% covered (danger)
0.00%
0 / 1
 resolve
n/a
0 / 0
n/a
0 / 0
0
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 add
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
12
 get
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
30
 clearAll
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Extension\Notifications\Cache;
4
5use Iterator;
6use MapCacheLRU;
7
8/**
9 * Base Local cache object, which borrows the concept from Flow user listener
10 */
11abstract class LocalCache {
12
13    /**
14     * Max number of objects to hold in $targets.  In theory, 1000
15     * is very hard to reach in a normal web request. We need to
16     * put cap, so it doesn't reach memory limit when running email
17     * digest against large amount of notifications
18     */
19    private const TARGET_MAX_NUM = 1000;
20
21    /**
22     * Target object cache
23     * @var MapCacheLRU
24     */
25    protected $targets;
26
27    /**
28     * Lookup ids that have not been resolved for a target
29     * @var bool[]
30     */
31    private $lookups = [];
32
33    /**
34     * Resolve ids in lookups to targets
35     *
36     * @param int[] $lookups
37     * @return Iterator
38     */
39    abstract protected function resolve( array $lookups );
40
41    /**
42     * Instances should be obtained via EchoServices / MediaWikiServices.
43     *
44     * @private
45     */
46    public function __construct() {
47        $this->targets = new MapCacheLRU( self::TARGET_MAX_NUM );
48    }
49
50    /**
51     * Add a key to the lookup and the key is used to resolve cache target
52     *
53     * @param int $key
54     */
55    public function add( $key ) {
56        if (
57            count( $this->lookups ) < self::TARGET_MAX_NUM
58            && !$this->targets->get( (string)$key )
59        ) {
60            $this->lookups[$key] = true;
61        }
62    }
63
64    /**
65     * Get the cache target based on the key
66     *
67     * @param int $key
68     * @return mixed|null
69     */
70    public function get( $key ) {
71        $target = $this->targets->get( (string)$key );
72        if ( $target ) {
73            return $target;
74        }
75
76        if ( isset( $this->lookups[ $key ] ) ) {
77            // Resolve the lookup batch and store results in the cache
78            $targets = $this->resolve( array_keys( $this->lookups ) );
79            foreach ( $targets as $id => $val ) {
80                $this->targets->set( $id, $val );
81            }
82            $this->lookups = [];
83            $target = $this->targets->get( (string)$key );
84            if ( $target ) {
85                return $target;
86            }
87        }
88
89        return null;
90    }
91
92    /**
93     * Clear everything in local cache
94     */
95    public function clearAll() {
96        $this->targets->clear();
97        $this->lookups = [];
98    }
99
100}