/** @var string Commit/rollback is from the connection manager for the IDatabase handle */
const FLUSHING_ALL_PEERS = 'flush';
/** @var string Commit/rollback is from the IDatabase handle internally */
- const FLUSHING_INTERNAL = 'flush';
+ const FLUSHING_INTERNAL = 'flush-internal';
/** @var string Do not remember the prior flags */
const REMEMBER_NOTHING = '';
public function writesPending();
/**
- * Returns true if there is a transaction/round open with possible write
- * queries or transaction pre-commit/idle callbacks waiting on it to finish.
+ * @return bool Whether there is a transaction open with pre-commit callbacks pending
+ * @since 1.32
+ */
+ public function preCommitCallbacksPending();
+
+ /**
+ * Whether there is a transaction open with either possible write queries
+ * or unresolved pre-commit/commit/resolution callbacks pending
+ *
* This does *not* count recurring callbacks, e.g. from setTransactionListener().
*
* @return bool
*
* @note: do not assume that *other* IDatabase instances will be AUTOCOMMIT mode
*
- * The callback takes one argument:
+ * The callback takes the following arguments:
* - How the transaction ended (IDatabase::TRIGGER_COMMIT or IDatabase::TRIGGER_ROLLBACK)
+ * - This IDatabase instance (since 1.32)
*
* @param callable $callback
* @param string $fname Caller name
* It can also be used for updates that easily suffer from lock timeouts and deadlocks,
* but where atomicity is not essential.
*
+ * Avoid using IDatabase instances aside from this one in the callback, unless such instances
+ * never have IDatabase::DBO_TRX set. This keeps callbacks from interfering with one another.
+ *
* Updates will execute in the order they were enqueued.
*
* @note: do not assume that *other* IDatabase instances will be AUTOCOMMIT mode
*
- * The callback takes one argument:
+ * The callback takes the following arguments:
* - How the transaction ended (IDatabase::TRIGGER_COMMIT or IDatabase::TRIGGER_IDLE)
+ * - This IDatabase instance (since 1.32)
*
* @param callable $callback
* @param string $fname Caller name
*
* Updates will execute in the order they were enqueued.
*
+ * The callback takes the one argument:
+ * - This IDatabase instance (since 1.32)
+ *
* @param callable $callback
* @param string $fname Caller name
* @since 1.22
* - This IDatabase object
* Callbacks must commit any transactions that they begin.
*
- * Registering a callback here will not affect writesOrCallbacks() pending
+ * Registering a callback here will not affect writesOrCallbacks() pending.
+ *
+ * Since callbacks from this method or onTransactionIdle() can start and end transactions,
+ * a single call to IDatabase::commit might trigger multiple runs of the listener callbacks.
*
* @param string $name Callback name
* @param callable|null $callback Use null to unset a listener
* Example usage (atomic changes that might have to be discarded):
* @code
* // Start a transaction if there isn't one already
- * $dbw->startAtomic( __METHOD__, $dbw::ATOMIC_CANCELABLE );
+ * $sectionId = $dbw->startAtomic( __METHOD__, $dbw::ATOMIC_CANCELABLE );
* // Create new record metadata row
* $dbw->insert( 'records', $row, __METHOD__ );
* // Figure out where to store the data based on the new row's ID
* $dbw->endAtomic( __METHOD__ );
* } else {
* // Discard these writes from the transaction (preserving prior writes)
- * $dbw->cancelAtomic( __METHOD__ );
+ * $dbw->cancelAtomic( __METHOD__, $sectionId );
* }
* @endcode
*
* $this->blobStore->delete( $path );
* }
* },
- * },
- * __METHOD__
- * );
+ * __METHOD__
+ * );
+ * }, $dbw::ATOMIC_CANCELABLE );
* @endcode
*
* Example usage, caller of the "RecordStore::save" method:
* try {
* $recordStore->save( $record );
* } catch ( StoreFailureException $e ) {
- * $dbw->cancelAtomic( __METHOD__ );
* // ...various SQL writes happen...
* }
* // ...various SQL writes happen...