Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
RequestTimeout
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
4 / 4
6
100.00% covered (success)
100.00%
1 / 1
 singleton
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setInstance
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 factory
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 createCriticalSectionProvider
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 enterCriticalSection
n/a
0 / 0
n/a
0 / 0
0
 exitCriticalSection
n/a
0 / 0
n/a
0 / 0
0
 setWallTimeLimit
n/a
0 / 0
n/a
0 / 0
0
 getWallTimeRemaining
n/a
0 / 0
n/a
0 / 0
0
 getWallTimeLimit
n/a
0 / 0
n/a
0 / 0
0
1<?php
2declare( strict_types = 1 );
3
4namespace Wikimedia\RequestTimeout;
5
6use Wikimedia\RequestTimeout\Detail\BasicRequestTimeout;
7use Wikimedia\RequestTimeout\Detail\ExcimerRequestTimeout;
8
9abstract class RequestTimeout {
10    /** @var RequestTimeout|null The singleton instance */
11    private static $instance;
12
13    /**
14     * Get a singleton instance of RequestTimeout. If the Excimer extension is
15     * loaded, this will return a fully functional implementation. If it is
16     * not loaded, a fallback implementation will be returned.
17     *
18     * @return RequestTimeout
19     */
20    public static function singleton() {
21        if ( !self::$instance ) {
22            self::$instance = self::factory();
23        }
24        return self::$instance;
25    }
26
27    /**
28     * Set the instance to be returned by singleton(), or null to clear the
29     * instance so that it will be recreated.
30     *
31     * @param RequestTimeout|null $instance
32     */
33    public static function setInstance( ?RequestTimeout $instance ) {
34        self::$instance = $instance;
35    }
36
37    /**
38     * Create a new instance of RequestTimeout. If the Excimer extension is
39     * loaded, this will return a fully functional implementation. If it is
40     * not loaded, a fallback implementation will be returned.
41     *
42     * @return RequestTimeout
43     */
44    public static function factory() {
45        if ( extension_loaded( 'excimer' ) ) {
46            return new ExcimerRequestTimeout;
47        } else {
48            // @codeCoverageIgnoreStart
49            return new BasicRequestTimeout;
50            // @codeCoverageIgnoreEnd
51        }
52    }
53
54    /**
55     * Create a CriticalSectionProvider with the specified configuration.
56     *
57     * @param float $emergencyLimit The emergency timeout in seconds
58     * @param callable|null $emergencyCallback A callback to call when the
59     *   emergency timeout expires. If null, an exception will be thrown.
60     * @param callable|null $implicitExitCallback A callback to call if a
61     *   critical section scope is exited implicitly, rather than by calling
62     *   exit().
63     * @return CriticalSectionProvider
64     */
65    public function createCriticalSectionProvider(
66        $emergencyLimit, $emergencyCallback = null, $implicitExitCallback = null
67    ) {
68        return new CriticalSectionProvider( $this, $emergencyLimit,
69            $emergencyCallback, $implicitExitCallback );
70    }
71
72    /**
73     * @internal For use by CriticalSectionProvider
74     *
75     * @param string $name
76     * @param float $emergencyLimit
77     * @param callable|null $emergencyCallback
78     * @return int
79     */
80    abstract public function enterCriticalSection( $name, $emergencyLimit, $emergencyCallback );
81
82    /**
83     * @internal For use by CriticalSectionProvider
84     *
85     * @throws TimeoutException
86     * @param int $id
87     */
88    abstract public function exitCriticalSection( $id );
89
90    /**
91     * Set the wall time limit. If excimer is available, an exception will be
92     * thrown after the specified number of seconds.
93     *
94     * If excimer is not available, this falls back to set_time_limit(), which
95     * causes a fatal error after the CPU time (not wall clock time) exceeds
96     * the given number of seconds, which is rounded to an integer.
97     *
98     * A time limit of INF or 0 is interpreted as no limit.
99     *
100     * @param float $limit The limit in seconds
101     */
102    abstract public function setWallTimeLimit( $limit );
103
104    /**
105     * Get the amount of time remaining of the limit. If there is no limit, INF
106     * will be returned.
107     *
108     * @return float
109     */
110    abstract public function getWallTimeRemaining();
111
112    /**
113     * Get the current wall time limit, or INF if there is no limit
114     *
115     * @return float
116     */
117    abstract public function getWallTimeLimit();
118}