Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5988851
CriticalSectionProvider.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
CriticalSectionProvider.php
View Options
<?php
namespace
Wikimedia\RequestTimeout
;
/**
* A class providing a named critical section concept. When the code is inside
* a critical section, if a request timeout occurs, it is queued and then
* delivered when the critical section exits.
*
* The class stores configuration for "emergency timeouts". This is a second
* timeout which limits the amount of time a critical section may be open.
*/
class
CriticalSectionProvider
{
/** @var RequestTimeout */
private
$requestTimeout
;
/** @var float */
private
$emergencyLimit
;
/** @var callable|null */
private
$emergencyCallback
;
/** @var callable|null */
private
$implicitExitCallback
;
/** @var array */
private
$stack
=
[];
/**
* @internal Use RequestTimeout::createCriticalSectionProvider()
*
* @param RequestTimeout $requestTimeout The parent object
* @param float $emergencyLimit The emergency timeout in seconds
* @param callable|null $emergencyCallback A callback to call when the
* emergency timeout expires. If null, an exception will be thrown.
* @param callable|null $implicitExitCallback A callback to call when a scoped
* critical section is exited implicitly by scope destruction, rather than
* by CriticalSectionScope::exit().
*/
public
function
__construct
(
RequestTimeout
$requestTimeout
,
$emergencyLimit
,
$emergencyCallback
,
$implicitExitCallback
)
{
$this
->
requestTimeout
=
$requestTimeout
;
$this
->
emergencyLimit
=
$emergencyLimit
;
$this
->
emergencyCallback
=
$emergencyCallback
;
$this
->
implicitExitCallback
=
$implicitExitCallback
;
}
/**
* Enter a critical section, giving it a name. The name should uniquely
* identify the calling code.
*
* Multiple critical sections may be active at a given time. Critical
* sections created by this method must be exited in the reverse order to
* which they were created, i.e. there is a stack of named critical
* sections.
*
* @param string $name
* @param float|null $emergencyLimit If non-null, this will override the
* configured emergency timeout
* @param callable|null $emergencyCallback If non-null, this will override
* the configured emergency timeout callback.
*/
public
function
enter
(
$name
,
$emergencyLimit
=
null
,
$emergencyCallback
=
null
)
{
$id
=
$this
->
requestTimeout
->
enterCriticalSection
(
$name
,
$emergencyLimit
??
$this
->
emergencyLimit
,
$emergencyCallback
??
$this
->
emergencyCallback
);
$this
->
stack
[
count
(
$this
->
stack
)
]
=
[
'name'
=>
$name
,
'id'
=>
$id
];
}
/**
* Exit a named critical section. If the name does not match the most recent
* call to enter(), an exception will be thrown.
*
* @throws CriticalSectionMismatchException
* @throws TimeoutException
* @param string $name
*/
public
function
exit
(
$name
)
{
$i
=
count
(
$this
->
stack
)
-
1
;
if
(
$i
===
-
1
)
{
throw
new
CriticalSectionMismatchException
(
$name
,
'[none]'
);
}
if
(
$this
->
stack
[
$i
][
'name'
]
!==
$name
)
{
throw
new
CriticalSectionMismatchException
(
$name
,
$this
->
stack
[
$i
][
'name'
]
);
}
$this
->
requestTimeout
->
exitCriticalSection
(
$this
->
stack
[
$i
][
'id'
]
);
unset
(
$this
->
stack
[
$i
]
);
}
/**
* Enter a critical section, and return a scope variable. The critical
* section will automatically exit when the scope variable is destroyed.
*
* Multiple critical sections may be active at a given time. There is no
* restriction on the order in which critical sections created by this
* method are exited.
*
* NOTE: Callers should typically call CriticalSectionScope::exit() instead
* of waiting for __destruct() to be called, since exiting a critical
* section may throw a timeout exception, but it is a fatal error to throw
* an exception from a destructor during request shutdown.
*
* @param string $name A name for the critical section, used in error messages
* @param float|null $emergencyLimit If non-null, this will override the
* configured emergency timeout
* @param callable|null $emergencyCallback If non-null, this will override
* the configured emergency timeout callback.
* @param callable|null $implicitExitCallback If non-null, this will override
* the configured implicit exit callback. The callback will be called if the
* section is exited in __destruct() instead of by calling exit().
* @return CriticalSectionScope
*/
public
function
scopedEnter
(
$name
,
$emergencyLimit
=
null
,
$emergencyCallback
=
null
,
$implicitExitCallback
=
null
)
{
$id
=
$this
->
requestTimeout
->
enterCriticalSection
(
$name
,
$emergencyLimit
??
$this
->
emergencyLimit
,
$emergencyCallback
??
$this
->
emergencyCallback
);
return
new
CriticalSectionScope
(
$id
,
function
(
$id
)
{
$this
->
requestTimeout
->
exitCriticalSection
(
$id
);
},
$implicitExitCallback
??
$this
->
implicitExitCallback
);
}
/**
* Get the configured emergency time limit
*
* @since 1.1.0
* @return float
*/
public
function
getEmergencyLimit
()
{
return
$this
->
emergencyLimit
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sun, Oct 4, 00:56 (3 w, 2 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
27/0a/3ef04935102f7b611e7dd4cb114b
Default Alt Text
CriticalSectionProvider.php (4 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment