Inject MultiWriteBagOStuff addCallableUpdate() dependency
Inject the DeferredUpdates::addCallableUpdate method via the ObjectCache. This brings it closer to being able to move to /libs. Change-Id: Ifa0d893002c3d709a4dc7346c263a92162274bd7
This commit is contained in:
parent
442d4cb497
commit
1171cc00cd
3 changed files with 34 additions and 19 deletions
|
|
@ -33,6 +33,8 @@ class MultiWriteBagOStuff extends BagOStuff {
|
||||||
protected $caches;
|
protected $caches;
|
||||||
/** @var bool Use async secondary writes */
|
/** @var bool Use async secondary writes */
|
||||||
protected $asyncWrites = false;
|
protected $asyncWrites = false;
|
||||||
|
/** @var callback|null */
|
||||||
|
protected $asyncHandler;
|
||||||
|
|
||||||
/** Idiom for "write to all backends" */
|
/** Idiom for "write to all backends" */
|
||||||
const ALL = INF;
|
const ALL = INF;
|
||||||
|
|
@ -41,22 +43,23 @@ class MultiWriteBagOStuff extends BagOStuff {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* $params include:
|
* $params include:
|
||||||
* - caches: A numbered array of either ObjectFactory::getObjectFromSpec
|
* - caches: A numbered array of either ObjectFactory::getObjectFromSpec
|
||||||
* arrays yeilding BagOStuff objects or direct BagOStuff objects.
|
* arrays yeilding BagOStuff objects or direct BagOStuff objects.
|
||||||
* If using the former, the 'args' field *must* be set.
|
* If using the former, the 'args' field *must* be set.
|
||||||
* The first cache is the primary one, being the first to
|
* The first cache is the primary one, being the first to
|
||||||
* be read in the fallback chain. Writes happen to all stores
|
* be read in the fallback chain. Writes happen to all stores
|
||||||
* in the order they are defined. However, lock()/unlock() calls
|
* in the order they are defined. However, lock()/unlock() calls
|
||||||
* only use the primary store.
|
* only use the primary store.
|
||||||
* - replication: Either 'sync' or 'async'. This controls whether writes to
|
* - replication: Either 'sync' or 'async'. This controls whether writes
|
||||||
* secondary stores are deferred when possible. Async writes
|
* to secondary stores are deferred when possible. Async writes
|
||||||
* require the HHVM register_postsend_function() function.
|
* require setting 'asyncCallback'. HHVM register_postsend_function() function.
|
||||||
* Async writes can increase the chance of some race conditions
|
* Async writes can increase the chance of some race conditions
|
||||||
* or cause keys to expire seconds later than expected. It is
|
* or cause keys to expire seconds later than expected. It is
|
||||||
* safe to use for modules when cached values: are immutable,
|
* safe to use for modules when cached values: are immutable,
|
||||||
* invalidation uses logical TTLs, invalidation uses etag/timestamp
|
* invalidation uses logical TTLs, invalidation uses etag/timestamp
|
||||||
* validation against the DB, or merge() is used to handle races.
|
* validation against the DB, or merge() is used to handle races.
|
||||||
*
|
* - asyncHandler: callable that takes a callback and runs it after the
|
||||||
|
* current web request ends. In CLI mode, it should run it immediately.
|
||||||
* @param array $params
|
* @param array $params
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
|
|
@ -85,7 +88,14 @@ class MultiWriteBagOStuff extends BagOStuff {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->asyncWrites = isset( $params['replication'] ) && $params['replication'] === 'async';
|
$this->asyncHandler = isset( $params['asyncHandler'] )
|
||||||
|
? $params['asyncHandler']
|
||||||
|
: null;
|
||||||
|
$this->asyncWrites = (
|
||||||
|
isset( $params['replication'] ) &&
|
||||||
|
$params['replication'] === 'async' &&
|
||||||
|
is_callable( $this->asyncHandler )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -226,7 +236,8 @@ class MultiWriteBagOStuff extends BagOStuff {
|
||||||
} else {
|
} else {
|
||||||
// Secondary write in async mode: do not block this HTTP request
|
// Secondary write in async mode: do not block this HTTP request
|
||||||
$logger = $this->logger;
|
$logger = $this->logger;
|
||||||
DeferredUpdates::addCallableUpdate(
|
call_user_func(
|
||||||
|
$this->asyncHandler,
|
||||||
function () use ( $cache, $method, $args, $logger ) {
|
function () use ( $cache, $method, $args, $logger ) {
|
||||||
if ( !call_user_func_array( array( $cache, $method ), $args ) ) {
|
if ( !call_user_func_array( array( $cache, $method ), $args ) ) {
|
||||||
$logger->warning( "Async $method op failed" );
|
$logger->warning( "Async $method op failed" );
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,9 @@ class ObjectCache {
|
||||||
return call_user_func( $params['factory'], $params );
|
return call_user_func( $params['factory'], $params );
|
||||||
} elseif ( isset( $params['class'] ) ) {
|
} elseif ( isset( $params['class'] ) ) {
|
||||||
$class = $params['class'];
|
$class = $params['class'];
|
||||||
|
if ( $class === 'MultiWriteBagOStuff' && !isset( $params['asyncHandler'] ) ) {
|
||||||
|
$params['asyncHandler'] = 'DeferredUpdates::addCallableUpdate';
|
||||||
|
}
|
||||||
return new $class( $params );
|
return new $class( $params );
|
||||||
} else {
|
} else {
|
||||||
throw new MWException( "The definition of cache type \""
|
throw new MWException( "The definition of cache type \""
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@ class MultiWriteBagOStuffTest extends MediaWikiTestCase {
|
||||||
$this->cache2 = new HashBagOStuff();
|
$this->cache2 = new HashBagOStuff();
|
||||||
$this->cache = new MultiWriteBagOStuff( array(
|
$this->cache = new MultiWriteBagOStuff( array(
|
||||||
'caches' => array( $this->cache1, $this->cache2 ),
|
'caches' => array( $this->cache1, $this->cache2 ),
|
||||||
'replication' => 'async'
|
'replication' => 'async',
|
||||||
|
'asyncHandler' => 'DeferredUpdates::addCallableUpdate'
|
||||||
) );
|
) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue