private $callback;
/**
- * @param IDatabase $dbw
+ * @param IDatabase $dbw DB handle; update aborts if a transaction now this rolls back
* @param string $fname Caller name (usually __METHOD__)
* @param callable $callback
+ * @param IDatabase[] $conns Abort if a transaction now on one of these rolls back [optional]
* @see IDatabase::doAtomicSection()
*/
- public function __construct( IDatabase $dbw, $fname, callable $callback ) {
+ public function __construct( IDatabase $dbw, $fname, callable $callback, array $conns = [] ) {
$this->dbw = $dbw;
$this->fname = $fname;
$this->callback = $callback;
-
- if ( $this->dbw->trxLevel() ) {
- $this->dbw->onTransactionResolution( [ $this, 'cancelOnRollback' ], $fname );
+ // Register DB connections for which uncommitted changes are related to this update
+ $conns[] = $dbw;
+ foreach ( $conns as $conn ) {
+ if ( $conn->trxLevel() ) {
+ $conn->onTransactionResolution( [ $this, 'cancelOnRollback' ], $fname );
+ }
}
}
}
}
+ /**
+ * @private This method is public so that it works with onTransactionResolution()
+ * @param int $trigger
+ */
public function cancelOnRollback( $trigger ) {
if ( $trigger === IDatabase::TRIGGER_ROLLBACK ) {
$this->callback = null;
private $callback;
/**
- * @param IDatabase $dbw
+ * @param IDatabase $dbw DB handle; update aborts if a transaction now this rolls back
* @param string $fname Caller name (usually __METHOD__)
* @param callable $callback Callback that takes (IDatabase, method name string)
+ * @param IDatabase[] $conns Abort if a transaction now on one of these rolls back [optional]
*/
- public function __construct( IDatabase $dbw, $fname, callable $callback ) {
+ public function __construct( IDatabase $dbw, $fname, callable $callback, array $conns = [] ) {
$this->dbw = $dbw;
$this->fname = $fname;
$this->callback = $callback;
-
- if ( $this->dbw->trxLevel() ) {
- $this->dbw->onTransactionResolution( [ $this, 'cancelOnRollback' ], $fname );
+ // Register DB connections for which uncommitted changes are related to this update
+ $conns[] = $dbw;
+ foreach ( $conns as $conn ) {
+ if ( $conn->trxLevel() ) {
+ $conn->onTransactionResolution( [ $this, 'cancelOnRollback' ], $fname );
+ }
}
}
}
}
+ /**
+ * @private This method is public so that it works with onTransactionResolution()
+ * @param int $trigger
+ */
public function cancelOnRollback( $trigger ) {
if ( $trigger === IDatabase::TRIGGER_ROLLBACK ) {
$this->callback = null;
}
}
+ /**
+ * @private This method is public so that it works with onTransactionResolution()
+ * @param int $trigger
+ */
public function cancelOnRollback( $trigger ) {
if ( $trigger === IDatabase::TRIGGER_ROLLBACK ) {
$this->callback = null;
abstract protected function mysqlError( $conn = null );
protected function wasQueryTimeout( $error, $errno ) {
- return $errno == 2062;
+ // https://dev.mysql.com/doc/refman/8.0/en/client-error-reference.html
+ // https://phabricator.wikimedia.org/T170638
+ return in_array( $errno, [ 2062, 3024 ] );
}
public function replace( $table, $uniqueIndexes, $rows, $fname = __METHOD__ ) {
}
// See https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
- return in_array( $errno, [ 1022, 1216, 1217, 1137, 1146, 1051, 1054 ], true );
+ return in_array( $errno, [ 1022, 1062, 1216, 1217, 1137, 1146, 1051, 1054 ], true );
}
/**
public function setLocalDomainPrefix( $prefix ) {
$this->localDomain = new DatabaseDomain(
$this->localDomain->getDatabase(),
- null,
+ $this->localDomain->getSchema(),
$prefix
);