Schedule a callable to run after a transaction commit

Xon

Well-known member
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 \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
Top Bottom