asimlqt/transact

PHP事务库

1.0.0 2018-01-22 21:35 UTC

This package is not auto-updated.

Last update: 2024-09-15 05:02:34 UTC


README

Transact 是一个PHP事务库,类似于数据库事务的方式,但用于PHP代码。

其目的是能够执行多个动作,这些动作可能依赖于之前动作的成功完成才能执行下一个动作,并在失败的情况下,希望回滚到原始状态。

安装

使用以下composer命令安装

composer require asimlqt/transact

示例

以下示例创建了3个简单的动作,在executerevert方法中输出一些文本。此示例将在整个README中引用,只有更改将被列出。

use Asimlqt\Transact\TransactionManager;
use Asimlqt\Transact\Action;
use Asimlqt\Transact\TransactionFailedException;

$transactionManager = new TransactionManager();

class Action1 extends Action {
    public function execute() {
        echo "Action1 execute\n";
    }
    public function revert() {
        echo "Action1 revert\n";
    }
}

class Action2 extends Action {
    public function execute() {
        echo "Action2 execute\n";
    }
    public function revert() {
        echo "Action2 revert\n";
    }
}

class Action3 extends Action {
    public function execute() {
        echo "Action3 execute\n";
    }
    public function revert() {
        echo "Action3 revert\n";
    }
}

$transactionManager
    ->addAction(new Action1())
    ->addAction(new Action2())
    ->addAction(new Action3());

try {
    $transactionManager->execute();
    echo "Transaction completed successfully\n";
} catch (TransactionFailedException $e) {
    echo $e->getMessage() . "\n";
}

程序输出

Action1 execute
Action2 execute
Action3 execute
Transaction completed successfully

执行顺序

动作将按照添加的顺序执行。当发生错误时(例如抛出异常),将按照相反的顺序调用revert方法。最后成功动作的revert方法将被首先调用,然后是上一个动作,以此类推,直到第一个动作。

例如,如果第三个动作抛出异常,则将调用Action2revert方法,然后调用Action1revert方法。

class Action3 extends Action {
    public function execute() {
        echo "Action3 execute\n";
        throw new Exception();
    }
    public function revert() {
        echo "Action3 revert\n";
    }
}

输出将是

Action1 execute
Action2 execute
Action3 execute
Action2 revert
Action1 revert
Transaction failed

你可能已经注意到,Action3的执行方法抛出异常,为什么没有调用Action3的回滚方法?这是因为每个动作应该只执行一个任务,如果动作因为无法完成任务而抛出异常,那么就没有东西可以回滚了!

向动作传递数据

通常,动作需要一些数据来执行其任务,为此可以使用Intent对象,它是一个简单的数组包装器。它只有两个方法:getset。这将在调用执行方法之前自动注入到动作中。

$intent = new Asimlqt\Transact\Intent();
$intent->set("user", $user);
$transactionManager->setIntent($intent);

然后在动作中,你可以使用以下方式检索用户

    public function execute() {
        $user = $this->getIntent()->get("user");
        ...
    }

请注意,相同的intent对象将转发给所有动作,因此有可能覆盖数据。如果需要从一个动作向另一个动作传递数据,这也可以是有用的。

重试策略

如果动作由于某些外部因素无法完成任务,你可能想再次尝试执行该动作,例如执行API请求。可以为executerevert指定重试策略。它们是针对特定动作的,因此只能为单个动作指定重试策略,或者为不同的动作指定不同的策略。以下是一些当前可用的策略:

RetryNone

这是默认策略,如果你没有明确指定,则不执行任何重试。

RetryOnce

这将立即尝试再次执行动作,然后再将其标记为失败。

RetryNumTimes

这将重复尝试执行动作指定次数。

RetryAfter

这将延迟指定的微秒数后再次尝试请求。

你需要在将动作对象添加到事务管理器之前设置这些策略。

$action1 = new Action1();
$action1->setExecuteRetryPolicy(new Asimlqt\Transact\Retry\RetryOnce());
$transactionManager->addAction($action1);