}
/**
- * Given a set of conditions, fetch a revision.
+ * Given a set of conditions, fetch a revision
+ *
+ * This method is used then a revision ID is qualified and
+ * will incorporate some basic slave/master fallback logic
*
* @param array $conditions
* @param int $flags (optional)
*/
private static function newFromConds( $conditions, $flags = 0 ) {
$db = wfGetDB( ( $flags & self::READ_LATEST ) ? DB_MASTER : DB_SLAVE );
+
$rev = self::loadFromConds( $db, $conditions, $flags );
+ // Make sure new pending/committed revision are visibile later on
+ // within web requests to certain avoid bugs like T93866 and T94407.
+ if ( !$rev
+ && !( $flags & self::READ_LATEST )
+ && wfGetLB()->getServerCount() > 1
+ && wfGetLB()->hasOrMadeRecentMasterChanges()
+ ) {
+ $flags = self::READ_LATEST;
+ $db = wfGetDB( DB_MASTER );
+ $rev = self::loadFromConds( $db, $conditions, $flags );
+ }
+
if ( $rev ) {
$rev->mQueryFlags = $flags;
}
+
return $rev;
}
* @return string|bool The revision's text, or false on failure
*/
protected function loadText() {
-
// Caching may be beneficial for massive use of external storage
global $wgRevisionCacheExpiry, $wgMemc;
+
$textId = $this->getTextId();
$key = wfMemcKey( 'revisiontext', 'textid', $textId );
if ( $wgRevisionCacheExpiry ) {
$this->runOnTransactionPreCommitCallbacks();
$this->doCommit( $fname );
if ( $this->mTrxDoneWrites ) {
+ $this->mDoneWrites = microtime( true );
$this->getTransactionProfiler()->transactionWritingOut(
$this->mServer, $this->mDBname, $this->mTrxShortId );
}
$this->runOnTransactionPreCommitCallbacks();
$this->doCommit( $fname );
if ( $this->mTrxDoneWrites ) {
+ $this->mDoneWrites = microtime( true );
$this->getTransactionProfiler()->transactionWritingOut(
$this->mServer, $this->mDBname, $this->mTrxShortId );
}
}
/**
- * Determine if there are any pending changes that need to be rolled back
- * or committed.
+ * Determine if there are pending changes in a transaction by this thread
* @since 1.23
* @return bool
*/
return false;
}
+ /**
+ * Get the timestamp of the latest write query done by this thread
+ * @since 1.25
+ * @return float|bool UNIX timestamp or false
+ */
+ public function lastMasterChangeTimestamp() {
+ $lastTime = false;
+ // Always 0, but who knows.. :)
+ $masterIndex = $this->getWriterIndex();
+ foreach ( $this->mConns as $conns2 ) {
+ if ( empty( $conns2[$masterIndex] ) ) {
+ continue;
+ }
+ /** @var DatabaseBase $conn */
+ foreach ( $conns2[$masterIndex] as $conn ) {
+ $lastTime = max( $lastTime, $conn->lastDoneWrites() );
+ }
+ }
+ return $lastTime;
+ }
+
+ /**
+ * Check if this load balancer object had any recent or still
+ * pending writes issued against it by this PHP thread
+ *
+ * @param float $age How many seconds ago is "recent" [defaults to mWaitTimeout]
+ * @return bool
+ * @since 1.25
+ */
+ public function hasOrMadeRecentMasterChanges( $age = null ) {
+ $age = ( $age === null ) ? $this->mWaitTimeout : $age;
+
+ return ( $this->hasMasterChanges()
+ || $this->lastMasterChangeTimestamp() > microtime( true ) - $age );
+ }
+
/**
* @param mixed $value
* @return mixed
// Load the new revision object
if ( $this->mNewid ) {
$this->mNewRev = Revision::newFromId( $this->mNewid );
-
- if ( !$this->mNewRev && wfGetLB()->getServerCount() > 1 ) {
- // Try harder… This is being hit after a rollback where we show the
- // diff immediately after the edit happened. T93866
- $this->mNewRev = Revision::newFromId( $this->mNewid, Revision::READ_LATEST );
- }
} else {
$this->mNewRev = Revision::newFromTitle(
$this->getTitle(),