From 9b24b4d6510c59eea5a259e794149c15f01a5054 Mon Sep 17 00:00:00 2001 From: pandaLIU <563883861@qq.com> Date: Sat, 1 Oct 2022 10:12:33 +0800 Subject: [PATCH 1/3] Updated Log --- src/Core/Rpc/Runtime/Swow/SocketChannel.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Core/Rpc/Runtime/Swow/SocketChannel.php b/src/Core/Rpc/Runtime/Swow/SocketChannel.php index 1c82c8d..30e91d5 100644 --- a/src/Core/Rpc/Runtime/Swow/SocketChannel.php +++ b/src/Core/Rpc/Runtime/Swow/SocketChannel.php @@ -27,6 +27,8 @@ use Hyperf\Seata\Core\Rpc\Runtime\SocketChannelInterface; use Hyperf\Seata\Core\Rpc\Runtime\V1\ProtocolV1Decoder; use Hyperf\Seata\Core\Rpc\Runtime\V1\ProtocolV1Encoder; +use Hyperf\Seata\Logger\LoggerFactory; +use Hyperf\Seata\Logger\LoggerInterface; use Hyperf\Seata\Utils\Buffer\ByteBuffer; use Hyperf\Seata\Utils\Protocol\RpcMessageUtils; use Hyperf\Utils\ApplicationContext; @@ -49,6 +51,8 @@ class SocketChannel implements SocketChannelInterface protected Channel $sendChannel; + private LoggerInterface $logger; + public function __construct(Socket $socket, Address $address) { $this->socket = $socket; @@ -56,6 +60,7 @@ public function __construct(Socket $socket, Address $address) $container = ApplicationContext::getContainer(); $this->protocolEncoder = $container->get(ProtocolV1Encoder::class); $this->protocolDecoder = $container->get(ProtocolV1Decoder::class); + $this->logger = $container->get(LoggerFactory::class)->create(static::class); $this->sendChannel = new Channel(); $this->createRecvLoop(); // $this->createSendLoop(); @@ -64,7 +69,7 @@ public function __construct(Socket $socket, Address $address) public function sendSyncWithResponse(RpcMessage $rpcMessage, int $timeoutMillis) { $channel = new Channel(); - echo 'Ready to send the rpc message #' . RpcMessageUtils::toLogString($rpcMessage) . PHP_EOL; + $this->logger->debug('Ready to send the rpc message #' . RpcMessageUtils::toLogString($rpcMessage)); $this->responses[$rpcMessage->getId()] = $channel; $this->sendSyncWithoutResponse($rpcMessage, $timeoutMillis); return $channel->pop(); @@ -96,7 +101,7 @@ protected function createRecvLoop() $rpcMessage = $this->protocolDecoder->decode($byteBuffer); $processorManger->dispatch($this, $rpcMessage); - echo 'Recieved a rpc message #' . RpcMessageUtils::toLogString($rpcMessage) . PHP_EOL; + $this->logger->debug('Recieved a rpc message #' . RpcMessageUtils::toLogString($rpcMessage)); if (isset($this->responses[$rpcMessage->getId()])) { $responseChannel = $this->responses[$rpcMessage->getId()]; $responseChannel->push($rpcMessage); @@ -107,10 +112,10 @@ protected function createRecvLoop() // // var_dump('heartbeat', $rpcMessage); // } } catch (\InvalidArgumentException $exception) { - echo 'Recieved a rpc message fail error:' . $exception->getMessage() . PHP_EOL; + $this->logger->debug('Recieved a rpc message fail error:' . $exception->getMessage()); break; } catch (\Throwable $exception) { - echo 'Recieved a rpc message fail error:' . $exception->getMessage() . PHP_EOL; + $this->logger->debug( 'Recieved a rpc message fail error:' . $exception->getMessage()); break; } finally { isset($rpcMessage) && $this->responses[$rpcMessage->getId()]->close(); From 30d6a6ddfd5187a68fdbbe3c426ede161ea63b10 Mon Sep 17 00:00:00 2001 From: pandaLIU <563883861@qq.com> Date: Sat, 1 Oct 2022 13:07:42 +0800 Subject: [PATCH 2/3] Added pdo proxy --- src/ConfigProvider.php | 3 +- src/Core/Context/GlobalLockConfigHolder.php | 2 +- src/Core/Context/RootContext.php | 2 +- src/Exception/ExecutionException.php | 10 +- src/Rm/DataSource/ClassMap/Connector.php | 148 ++++++++++++++++++ src/Rm/DataSource/ConnectionContext.php | 2 +- src/Rm/PDOStatementProxy.php | 15 +- .../Transaction/TransactionHookManager.php | 2 +- src/Tm/Api/Transaction/TransactionInfo.php | 28 +--- src/Tm/Api/TransactionalTemplate.php | 11 +- 10 files changed, 183 insertions(+), 40 deletions(-) create mode 100644 src/Rm/DataSource/ClassMap/Connector.php diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index 36a2732..9ac4fe9 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -19,6 +19,7 @@ */ namespace Hyperf\Seata; +use Hyperf\Database\Connectors\Connector; use Hyperf\Seata\Annotation\GlobalTransactionScanner; use Hyperf\Seata\Core\Model\ResourceManagerInterface; use Hyperf\Seata\Listener\InitListener; @@ -40,7 +41,7 @@ public function __invoke(): array ResourceManagerInterface::class => DefaultResourceManager::class, // GlobalTransactionScanner::class => GlobalTransactionScannerFactory::class, LoggerInterface::class => StdoutLogger::class, - // DataSourceProxy::class => DataSourceProxyFactory::class, +// DataSourceProxy::class => DataSourceProxyFactory::class, ], ]; } diff --git a/src/Core/Context/GlobalLockConfigHolder.php b/src/Core/Context/GlobalLockConfigHolder.php index e485cee..0b42f08 100644 --- a/src/Core/Context/GlobalLockConfigHolder.php +++ b/src/Core/Context/GlobalLockConfigHolder.php @@ -20,7 +20,7 @@ namespace Hyperf\Seata\Core\Context; use Hyperf\Seata\Core\Model\GlobalLockConfig; -use Hyperf\Utils\Context; +use Hyperf\Context\Context; class GlobalLockConfigHolder { diff --git a/src/Core/Context/RootContext.php b/src/Core/Context/RootContext.php index efecdf3..174200e 100644 --- a/src/Core/Context/RootContext.php +++ b/src/Core/Context/RootContext.php @@ -24,7 +24,7 @@ use Hyperf\Seata\Logger\LoggerFactory; use Hyperf\Seata\Logger\LoggerInterface; use Hyperf\Utils\ApplicationContext; -use Hyperf\Utils\Context; +use Hyperf\Context\Context; use RuntimeException; class RootContext extends Context diff --git a/src/Exception/ExecutionException.php b/src/Exception/ExecutionException.php index f7b5f6b..d06c8b7 100644 --- a/src/Exception/ExecutionException.php +++ b/src/Exception/ExecutionException.php @@ -65,18 +65,10 @@ public function setTransaction(GlobalTransaction $transaction): void $this->transaction = $transaction; } - /** - * @return int - */ - public function getCode() - { - return $this->code; - } - /** * @param int $code */ - public function setCode($code): void + public function setCode(int $code): void { $this->code = $code; } diff --git a/src/Rm/DataSource/ClassMap/Connector.php b/src/Rm/DataSource/ClassMap/Connector.php new file mode 100644 index 0000000..36f4fbb --- /dev/null +++ b/src/Rm/DataSource/ClassMap/Connector.php @@ -0,0 +1,148 @@ + PDO::CASE_NATURAL, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, + PDO::ATTR_STRINGIFY_FETCHES => false, + PDO::ATTR_EMULATE_PREPARES => false, + ]; + + /** + * Create a new PDO connection. + * + * @param string $dsn + * @throws \Exception + * @return \PDO + */ + public function createConnection($dsn, array $config, array $options) + { + [$username, $password] = [ + $config['username'] ?? null, $config['password'] ?? null, + ]; + + try { + return $this->createPdoConnection( + $dsn, + $username, + $password, + $options + ); + } catch (Exception $e) { + return $this->tryAgainIfCausedByLostConnection( + $e, + $dsn, + $username, + $password, + $options + ); + } + } + + /** + * Get the PDO options based on the configuration. + * + * @return array + */ + public function getOptions(array $config) + { + return array_replace($this->options, $config['options'] ?? []); + } + + /** + * Get the default PDO connection options. + * + * @return array + */ + public function getDefaultOptions() + { + return $this->options; + } + + /** + * Set the default PDO connection options. + */ + public function setDefaultOptions(array $options) + { + $this->options = $options; + } + + /** + * Create a new PDO connection instance. + * + * @param string $dsn + * @param string $username + * @param string $password + * @param array $options + * @return \PDO + */ + protected function createPdoConnection($dsn, $username, $password, $options) + { + return new PDOProxy($dsn, $username, $password, $options); + } + + /** + * Determine if the connection is persistent. + * + * @param array $options + * @return bool + */ + protected function isPersistentConnection($options) + { + return isset($options[PDO::ATTR_PERSISTENT]) + && $options[PDO::ATTR_PERSISTENT]; + } + + /** + * Handle an exception that occurred during connect execution. + * + * @param string $dsn + * @param string $username + * @param string $password + * @param array $options + * @throws \Exception + * @return \PDO + */ + protected function tryAgainIfCausedByLostConnection(Throwable $e, $dsn, $username, $password, $options) + { + if ($this->causedByLostConnection($e)) { + return $this->createPdoConnection($dsn, $username, $password, $options); + } + + throw $e; + } +} \ No newline at end of file diff --git a/src/Rm/DataSource/ConnectionContext.php b/src/Rm/DataSource/ConnectionContext.php index ba43905..de1870f 100644 --- a/src/Rm/DataSource/ConnectionContext.php +++ b/src/Rm/DataSource/ConnectionContext.php @@ -21,7 +21,7 @@ use Hyperf\Seata\Exception\ShouldNeverHappenException; use Hyperf\Seata\Rm\DataSource\Undo\SQLUndoLog; -use Hyperf\Utils\Context; +use Hyperf\Context\Context; class ConnectionContext { diff --git a/src/Rm/PDOStatementProxy.php b/src/Rm/PDOStatementProxy.php index 25d2cf2..2d9f14c 100644 --- a/src/Rm/PDOStatementProxy.php +++ b/src/Rm/PDOStatementProxy.php @@ -50,6 +50,18 @@ public function __call(string $name, array $arguments) return $this->__object->{$name}(...$arguments); } + public function fetchAll($mode = PDO::FETCH_BOTH, $fetch_argument = null, ...$args) + { + $args = func_get_args(); + return $this->__object->fetchAll(...$args); + } + + public function setFetchMode($mode, $className = null, ...$params) + { + $args = func_get_args(); + return $this->__object->setFetchMode(...$args); + } + public function bindParam(int|string $param, mixed &$var, int $type = PDO::PARAM_INT, int $maxLength = null, mixed $driverOptions = null) { $this->bindParamContext[$param] = [$var, $type, $maxLength, $driverOptions]; @@ -70,6 +82,7 @@ public function bindValue(int|string $param, mixed $value, int $type = PDO::PARA public function execute(?array $params = null) { + if ($this->sqlParser->isDelete()) { $deleteExecutor = new DeleteExecutor($this->sqlParser, $this->PDOProxy, $this->bindParamContext, $this->bindColumnContext, $this->bindValueContext); $deleteExecutor->execute($params); @@ -80,6 +93,6 @@ public function execute(?array $params = null) if ($this->sqlParser->isInsert()) { } - return parent::execute($params); + return $this->__object->execute($params); } } diff --git a/src/Tm/Api/Transaction/TransactionHookManager.php b/src/Tm/Api/Transaction/TransactionHookManager.php index 61dfb68..3439a09 100644 --- a/src/Tm/Api/Transaction/TransactionHookManager.php +++ b/src/Tm/Api/Transaction/TransactionHookManager.php @@ -19,7 +19,7 @@ */ namespace Hyperf\Seata\Tm\Api\Transaction; -use Hyperf\Utils\Context; +use Hyperf\Context\Context; class TransactionHookManager { diff --git a/src/Tm/Api/Transaction/TransactionInfo.php b/src/Tm/Api/Transaction/TransactionInfo.php index 4cba997..d19b73c 100644 --- a/src/Tm/Api/Transaction/TransactionInfo.php +++ b/src/Tm/Api/Transaction/TransactionInfo.php @@ -23,35 +23,21 @@ class TransactionInfo { - /** - * @var int - */ - private $timeOut; + private int $timeOut; - /** - * @var string - */ - private $name; + private string $name; /** * @var RollbackRule[] */ - private $rollbackRules; + private array $rollbackRules = []; - /** - * @var Propagation - */ - private $propagation; + private ?Propagation $propagation = null; - /** - * @var int - */ - private $lockRetryInterval; + private int $lockRetryInterval; + + private int $lockRetryTimes; - /** - * @var int - */ - private $lockRetryTimes; public function getTimeOut(): int { diff --git a/src/Tm/Api/TransactionalTemplate.php b/src/Tm/Api/TransactionalTemplate.php index 8b99645..9e4221d 100644 --- a/src/Tm/Api/TransactionalTemplate.php +++ b/src/Tm/Api/TransactionalTemplate.php @@ -27,19 +27,21 @@ use Hyperf\Seata\Exception\ExecutionException; use Hyperf\Seata\Exception\ShouldNeverHappenException; use Hyperf\Seata\Exception\TransactionException; +use Hyperf\Seata\Logger\LoggerFactory; use Hyperf\Seata\Tm\Api\Transaction\Propagation; use Hyperf\Seata\Tm\Api\Transaction\TransactionHook; use Hyperf\Seata\Tm\Api\Transaction\TransactionHookManager; use Hyperf\Seata\Tm\Api\Transaction\TransactionInfo; +use Psr\Log\LoggerInterface; use Throwable; class TransactionalTemplate { - private StdoutLoggerInterface $logger; + private LoggerInterface $logger; - public function __construct(StdoutLoggerInterface $logger) + public function __construct(LoggerFactory $loggerFactory) { - $this->logger = $logger; + $this->logger = $loggerFactory->create(static::class); } public function execute(TransactionalExecutor $business) @@ -113,13 +115,14 @@ public function execute(TransactionalExecutor $business) // 2. If the tx role is 'GlobalTransactionRole.Launcher', send the request of beginTransaction to TC, // else do nothing. Of course, the hooks will still be triggered. $this->beginTransaction($txInfo, $tx); - $rs = null; try { // Do Your Business $rs = $business->execute(); } catch (Throwable $throwable) { // 3. The needed business exception to rollback. + var_dump($throwable->getMessage()); + var_dump($throwable->getTraceAsString()); $this->completeTransactionAfterThrowing($txInfo, $tx, $throwable); throw $throwable; } From f760f781f66d0eecd753a5f7007f04372b9d04ef Mon Sep 17 00:00:00 2001 From: pandaLIU <563883861@qq.com> Date: Sat, 1 Oct 2022 13:08:46 +0800 Subject: [PATCH 3/3] remove var_dump --- src/Tm/Api/TransactionalTemplate.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Tm/Api/TransactionalTemplate.php b/src/Tm/Api/TransactionalTemplate.php index 9e4221d..f78e913 100644 --- a/src/Tm/Api/TransactionalTemplate.php +++ b/src/Tm/Api/TransactionalTemplate.php @@ -121,8 +121,6 @@ public function execute(TransactionalExecutor $business) $rs = $business->execute(); } catch (Throwable $throwable) { // 3. The needed business exception to rollback. - var_dump($throwable->getMessage()); - var_dump($throwable->getTraceAsString()); $this->completeTransactionAfterThrowing($txInfo, $tx, $throwable); throw $throwable; }