public function transaction(callable $run, $attempts=1)
    {

        if ($attempts < 1) {
            throw new InvalidArgumentException("Invalid transaction attempts: $attempts");
        }

        for ($i = 1; $i <= $attempts; $i++) {

            $this->begin();

            try {
                $result = $run($this);
                $this->commit();
                return $result;
            } catch (SQLLockException $e) {
                $this->rollback();
                continue;
            } catch (\Exception $e) {
                $this->rollback();
                throw $this->convertException($e);
            }
        }

        return false;
    }