I've had a couple cases where I've needed to run some callable after a transaction commits which have been super-awkward to fit into XF's code structure as sometimes the hook point to "do stuff" after the transaction just isn't there but I can run my code inside the transaction.
For things like sending moderator alerts or similar, these often should go outside the transaction as they touch xf_user/xf_user_alert rows and can pull in locking for large tables, but need to be queued & triggered only if the the transaction finishes successfully.
Similar to
Implementation wise, this is just pushing a callable onto an array which is cleared on rollback & called on commit with something like:
The actual use-case was in some private add-on code was to increment some custom stats tables outside of the post/thread/forum transactions to avoid a dependency between that stats table and the standard post/thread/forum tables.
For things like sending moderator alerts or similar, these often should go outside the transaction as they touch xf_user/xf_user_alert rows and can pull in locking for large tables, but need to be queued & triggered only if the the transaction finishes successfully.
Similar to
\XF\Db\Mysqli\Adapter::runAfterCommit
, with the signature being:
PHP:
public function runAfterCommit(callable $closure, ?string $uniqueKey = null): void
Implementation wise, this is just pushing a callable onto an array which is cleared on rollback & called on commit with something like:
PHP:
public function commit(): void
{
$wasInTransaction = $this->inTransaction;
parent::commit();
if ($wasInTransaction && !$this->inTransaction) {
$callables = $this->postTransactionCallables;
$this->postTransactionCallables = [];
foreach ($callables as $callable) {
$callable();
}
}
}
The actual use-case was in some private add-on code was to increment some custom stats tables outside of the post/thread/forum transactions to avoid a dependency between that stats table and the standard post/thread/forum tables.
Upvote
5