johmanx10/transaction
Composer 安装命令:
composer require johmanx10/transaction
包简介
Handles operations with automatic rollback mechanisms.
关键字:
README 文档
README
Introduction
Transaction handles operations with automatic rollback mechanisms.
A transaction consists of operations. When an operation fails, it traverses back up the chain, rolling back all previous operations in reverse order.
Assume a situation where filesystem operations need to be automated. If a part of the operations fail, the filesystem needs to be restored to the state before all operations were applied. Given the following operations:
- Create directory
my-app - Copy file
dist/consoletomy-app/bin/console - Add executable rights to
my-app/bin/console
This will be handled as follows:
- ✔ Create directory
my-app. - ∴ Copy file
dist/consoletomy-app/bin/console- Directorymy-app/bindoes not exist. - ✔ Rollback: if
my-app/bin/consoleexists, remove it. - ✔ Rollback: if
my-appexists, remove it.
An example of the above can be tested locally by
running examples/file-operations from a command line terminal.
Every operation is responsible for defining their own rollback mechanism. That way, complex nested structures to check and roll back operations can be constructed vertically.
Installation
composer require johmanx10/transaction
Processing operations
To process a list of ordered operations, either use a transaction, or a handler.
Transaction
A transaction is more straight-forward and better suited to less complicated transactional scripts.
<?php use Johmanx10\Transaction\Transaction; use Johmanx10\Transaction\OperationInterface; use Johmanx10\Transaction\Exception\TransactionRolledBackException; use Johmanx10\Transaction\Exception\FailedRollbackException; use Johmanx10\Transaction\Visitor\OperationVisitorInterface; /** @var OperationInterface[] $operations */ $transaction = new Transaction(...$operations); try { /** @var OperationVisitorInterface[] $visitors */ $transaction->commit(...$visitors); } catch (TransactionRolledBackException $rollback) { // Do something with the operations that were rolled back. // This exception contains a method to get all failed operations, paired // with any exception that triggered the rollback. } catch (FailedRollbackException $rollbackException) { // Do something if an operation could not be rolled back. // This exception contains the affected operation, as well as a list of // operations that have successfully rolled back up to the point where the // current operation could not. }
Operation Handler
The operation handler is better suited in a service oriented application. It allows to prepare visitors separate from the invoking code and thus separates concerns about operations and their visitors.
<?php use Johmanx10\Transaction\Exception\OperationExceptionInterface; use Johmanx10\Transaction\OperationHandler; use Johmanx10\Transaction\OperationInterface; use Johmanx10\Transaction\Visitor\LogOperationVisitor; use Psr\Log\LoggerInterface; $handler = new OperationHandler(); $handler->attachVisitor( /** @var LoggerInterface $logger */ new LogOperationVisitor($logger) );; try { /** @var OperationInterface[] $operations */ $handler->handle(...$operations); } catch (OperationExceptionInterface $exception) { // Get the formatted internal exception. $formatted = $exception->getMessage(); // Get the operation that caused the exception. $operation = $exception->getOperation(); // Get the exception that shows the context of the failure. $context = $exception->getPrevious(); }
The operation exception removes a lot of boiler plate code caused by the different exception formatters.
See a working example by running:
examples/operation-handler
Defining an operation
To create an operation, implement the OperationInterface,
DescribableOperationInterface or use the existing Operation class to create
an inline operation:
<?php use Johmanx10\Transaction\Operation; use Johmanx10\Transaction\Transaction; $appDir = __DIR__ . '/my-app'; $transaction = new Transaction( // Create the app directory. new Operation( // Create the new directory. function () use ($appDir) { if (!file_exists($appDir) && !@mkdir($appDir)) { throw new RuntimeException( sprintf('Could not create directory: "%s"', $appDir) ); } }, // Roll back the operation. function () use ($appDir) { if (file_exists($appDir) && !@rmdir($appDir)) { throw new RuntimeException( sprintf('Could not remove directory: "%s"', $appDir) ); } }, // Set the operation description. sprintf('Create directory: "%s"', $appDir) ) );
Formatting operations and exceptions
To better identify the operation, the operation failure or a specific exception, a number of formatters are available to help with debugging failed operations, chains of rolled back operations or failing rollbacks.
Operation formatter
The operation formatter can be used to format an operation.
If an operation implements the DescribableOperationInterface, it can be
converted to string and will be represented as such. Otherwise, it will create
a generic representation, with a unique identifier for the operation.
<?php use Johmanx10\Transaction\OperationInterface; use Johmanx10\Transaction\Formatter\OperationFormatterInterface; /** * @var OperationFormatterInterface $formatter * @var OperationInterface $operation */ $formatter->format($operation);
Operation failure formatter
An operation failure consists of an operation and optionally an exception.
When an operation failure is formatted, it determines a strategy based on whether an exception is set.
If an exception is set, the result will be marked with ∴ and uses the exception
message as description. When no exception is present, the result will be marked
with ✔ and uses the formatted operation as description.
An operation failure is formatted using the following pattern:
({operationId}){padding} {icon} {description}
In order, these show an operation failure with and without exception:
(2) ∴ Could not copy "dist/console" -> "my-app/bin/console".
(1) ✔ Create directory: "my-app"
Rollback formatter
The rollback formatter can be used to format caught instances of
TransactionRolledBackException.
<?php use Johmanx10\Transaction\Transaction; use Johmanx10\Transaction\OperationInterface; use Johmanx10\Transaction\Exception\TransactionRolledBackException; use Johmanx10\Transaction\Formatter\RollbackFormatter; /** @var OperationInterface[] $operations */ $transaction = new Transaction(...$operations); try { $transaction->commit(); } catch (TransactionRolledBackException $rollback) { $formatter = new RollbackFormatter(); echo $formatter->format($rollback) . PHP_EOL; }
If the code above tries to process 3 operations, but encounters a problem at the second operation, the formatted output may look something like:
2 operations were rolled back: 6, 2
Stacktrace:
(6) ∴ Could not copy "dist/console" -> "my-app/bin/console".
(2) ✔ Create directory: "my-app"
This shows that the first operation (2) succeeded and the second operation (6) failed. At that point the operations were rolled back in reverse order.
See a working example by running:
examples/file-operations
Failed rollback formatter
When operations are rolled back and midway one of the operations breaks on the
rollback, the FailedRollbackException will be thrown. It can be formatted
using the failed rollback formatter:
<?php use Johmanx10\Transaction\Transaction; use Johmanx10\Transaction\OperationInterface; use Johmanx10\Transaction\Exception\FailedRollbackException; use Johmanx10\Transaction\Formatter\FailedRollbackFormatter; /** @var OperationInterface[] $operations */ $transaction = new Transaction(...$operations); try { $transaction->commit(); } catch (FailedRollbackException $rollback) { $formatter = new FailedRollbackFormatter(); echo $formatter->format($rollback) . PHP_EOL; }
When operations Foo, Bar, Baz and Qux are executed in order and the
operation breaks at Qux, the rollback starts from Qux and moves back up.
If the rollback for Bar then breaks, the formatted output may look something
like:
Failed rolling back operation #5
Operation Bar
Could not rollback Bar.
Previous rollbacks:
(10) ∴ Failed operation Qux
(8) ✔ Operation Baz
This shows that the operation for Qux breaks the chain. Baz could be
successfully rolled back, but Bar could not and Foo is therefore completely
missing from this picture, because a rollback for Foo was never attempted.
The exception uses the following format:
Failed rolling back operation #{operationId}
{operationDescription}
{rollbackExceptionMessage}
And if there have been previous rollbacks, the following is appended:
Previous rollbacks:
{previousRollbacks}
Visiting operations
The default implementation of Transaction implements the interface
\Johmanx10\Transaction\Visitor\AcceptingTransactionInterface, allowing it to
accept operation visitors, implementing
\Johmanx10\Transaction\Visitor\OperationVisitorInterface.
This can be used to gather information about operations that are executed during a transaction commit.
The following shows how to log every operation that is about to be executed within the transaction:
<?php use Johmanx10\Transaction\OperationInterface; use Johmanx10\Transaction\Transaction; use Johmanx10\Transaction\Visitor\LogOperationVisitor; use Psr\Log\LoggerInterface; /** @var LoggerInterface $logger */ $visitor = new LogOperationVisitor($logger); /** @var OperationInterface[] $operations */ $transaction = new Transaction(...$operations); $transaction->commit($visitor);
johmanx10/transaction 适用场景与选型建议
johmanx10/transaction 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 43.33k 次下载、GitHub Stars 达 19, 最近一次更新时间为 2018 年 12 月 01 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「transaction」 「commit」 「rollback」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 johmanx10/transaction 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 johmanx10/transaction 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 johmanx10/transaction 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
DUKPT implementation in PHP
Laravel package for rolling back migrations between different releases
The BlockTrail PHP SDK, for integration of Bitcoin functionality through the BlockTrail API
Send mails after DB transaction is committed
This is a transaction.
Ansistrano configuration skeleton
统计信息
- 总下载量: 43.33k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 19
- 点击次数: 28
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2018-12-01