- $shutdownPositions = $this->shutdownPositions;
- $ok = $this->store->merge(
- $this->key,
- function ( $store, $key, $curValue ) use ( $shutdownPositions ) {
- /** @var $curPositions DBMasterPos[] */
- if ( $curValue === false ) {
- $curPositions = $shutdownPositions;
- } else {
- $curPositions = $curValue['positions'];
- // Use the newest positions for each DB master
- foreach ( $shutdownPositions as $db => $pos ) {
- if ( !isset( $curPositions[$db] )
- || $pos->asOfTime() > $curPositions[$db]->asOfTime()
- ) {
- $curPositions[$db] = $pos;
- }
- }
- }
-
- return [ 'positions' => $curPositions ];
- },
- BagOStuff::TTL_MINUTE,
- 10,
- BagOStuff::WRITE_SYNC // visible in all datacenters
- );
+ // CP-protected writes should overwhemingly go to the master datacenter, so get DC-local
+ // lock to merge the values. Use a DC-local get() and a synchronous all-DC set(). This
+ // makes it possible for the BagOStuff class to write in parallel to all DCs with one RTT.
+ if ( $this->store->lock( $this->key, 3 ) ) {
+ $ok = $this->store->set(
+ $this->key,
+ self::mergePositions( $this->store->get( $this->key ), $this->shutdownPositions ),
+ BagOStuff::TTL_MINUTE,
+ BagOStuff::WRITE_SYNC
+ );
+ $this->store->unlock( $this->key );
+ } else {
+ $ok = false;
+ }