Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

二阶段消息的例子解释 #2

Open
313964535 opened this issue Sep 29, 2022 · 2 comments
Open

二阶段消息的例子解释 #2

313964535 opened this issue Sep 29, 2022 · 2 comments

Comments

@313964535
Copy link

image

这个doAdminSubmit方法里面的代码是成功的时候执行的还是失败的时候执行的啊,如果这个例子换成跨行转账的话,应该是怎么样的呢? 为什么没有看到操作数据库的代码啊,就是 余额的增加和减少这种
@qiannianlei
Copy link

项目中提供的二阶段消息示例不够完整,以下是我自己做的实验,仅供参考:

<?php

namespace App\Controller;

use DtmClient\Api\ApiInterface;
use DtmClient\Api\RequestBranch;
use DtmClient\Barrier;
use DtmClient\BranchIdGeneratorInterface;
use DtmClient\Constants\Result;
use DtmClient\Exception\FailureException;
use DtmClient\Msg;
use DtmClient\TransContext;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\HttpServer\Annotation\RequestMapping;

#[Controller()]
class MsgController extends AbstractController
{
    private Msg $msg;

    protected ApiInterface $api;

    protected Barrier $barrier;

    protected BranchIdGeneratorInterface $branchIdGenerator;

    public function __construct(Msg $msg, ApiInterface $api, Barrier $barrier, BranchIdGeneratorInterface $branchIdGenerate)
    {
        $this->msg = $msg;
        $this->api = $api;
        $this->barrier = $barrier;
        $this->branchIdGenerator = $branchIdGenerate;
    }

    #[RequestMapping(path: 'msg')]
    public function msg()
    {
        $gid = $this->msg->generateGid();
        TransContext::setGid($gid);

        $req = $this->genReqHTTP(30);

        $this->msg->add($this->serviceUri . '/msg/transIn', $req);

        $this->msg->doAndSubmit($this->serviceUri . '/msg/QueryPreparedB', function () {

            // 如果转出服务 跟 AP是同一个服务,可以不走网络请求,直接调用本地方法

            // 1、网络请求
            $branchId = $this->branchIdGenerator->generateSubBranchId();

            $branchRequest = new RequestBranch();
            $branchRequest->method = 'POST';
            $branchRequest->url = $this->serviceUri . '/msg/transOut';
            $branchRequest->branchId = TransContext::getBranchId();
            $branchRequest->op = TransContext::getOp();
            $branchRequest->body = ['amount' => -30];
            return $this->api->transRequestBranch($branchRequest);

            // 2、本地方法调用
//            $this->barrier->call(function (){
//                $this->localTransOut();
//            });
        });
    }

    protected function localTransOut()
    {
        // 业务逻辑处理,处理失败抛异常
        echo '本地方法转出金额30'.PHP_EOL;
    }


    protected function genReqHTTP(int $amount): array
    {
        return [
            'amount' => $amount,
            'transInResult' => '',
            'transOutResult' => '',
            'store' => '',
        ];
    }

    #[PostMapping(path: 'transIn')]
    public function transIn()
    {
        echo '转入金额30'.PHP_EOL;
    }

    #[PostMapping(path: 'transOut')]
    #[\DtmClient\Annotation\Barrier]
    public function transOut()
    {
        echo '转出金额-30'.PHP_EOL;
    }

    #[GetMapping(path: 'QueryPreparedB')]
    public function queryPrepared()
    {
        echo 'queryPrepared'.PHP_EOL;
        $params = $this->request->all();
        try {
            $this->barrier->queryPrepared($params['trans_type'], $params['gid']);
            return Result::SUCCESS;
        } catch (FailureException $throwable){
            return Result::FAILURE;
        }
    }
}

@guanyutao92
Copy link

guanyutao92 commented Sep 6, 2023

项目中提供的二阶段消息示例不够完整,以下是我自己做的实验,仅供参考:

<?php

namespace App\Controller;

use DtmClient\Api\ApiInterface;
use DtmClient\Api\RequestBranch;
use DtmClient\Barrier;
use DtmClient\BranchIdGeneratorInterface;
use DtmClient\Constants\Result;
use DtmClient\Exception\FailureException;
use DtmClient\Msg;
use DtmClient\TransContext;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\HttpServer\Annotation\RequestMapping;

#[Controller()]
class MsgController extends AbstractController
{
    private Msg $msg;

    protected ApiInterface $api;

    protected Barrier $barrier;

    protected BranchIdGeneratorInterface $branchIdGenerator;

    public function __construct(Msg $msg, ApiInterface $api, Barrier $barrier, BranchIdGeneratorInterface $branchIdGenerate)
    {
        $this->msg = $msg;
        $this->api = $api;
        $this->barrier = $barrier;
        $this->branchIdGenerator = $branchIdGenerate;
    }

    #[RequestMapping(path: 'msg')]
    public function msg()
    {
        $gid = $this->msg->generateGid();
        TransContext::setGid($gid);

        $req = $this->genReqHTTP(30);

        $this->msg->add($this->serviceUri . '/msg/transIn', $req);

        $this->msg->doAndSubmit($this->serviceUri . '/msg/QueryPreparedB', function () {

            // 如果转出服务 跟 AP是同一个服务,可以不走网络请求,直接调用本地方法

            // 1、网络请求
            $branchId = $this->branchIdGenerator->generateSubBranchId();

            $branchRequest = new RequestBranch();
            $branchRequest->method = 'POST';
            $branchRequest->url = $this->serviceUri . '/msg/transOut';
            $branchRequest->branchId = TransContext::getBranchId();
            $branchRequest->op = TransContext::getOp();
            $branchRequest->body = ['amount' => -30];
            return $this->api->transRequestBranch($branchRequest);

            // 2、本地方法调用
//            $this->barrier->call(function (){
//                $this->localTransOut();
//            });
        });
    }

    protected function localTransOut()
    {
        // 业务逻辑处理,处理失败抛异常
        echo '本地方法转出金额30'.PHP_EOL;
    }


    protected function genReqHTTP(int $amount): array
    {
        return [
            'amount' => $amount,
            'transInResult' => '',
            'transOutResult' => '',
            'store' => '',
        ];
    }

    #[PostMapping(path: 'transIn')]
    public function transIn()
    {
        echo '转入金额30'.PHP_EOL;
    }

    #[PostMapping(path: 'transOut')]
    #[\DtmClient\Annotation\Barrier]
    public function transOut()
    {
        echo '转出金额-30'.PHP_EOL;
    }

    #[GetMapping(path: 'QueryPreparedB')]
    public function queryPrepared()
    {
        echo 'queryPrepared'.PHP_EOL;
        $params = $this->request->all();
        try {
            $this->barrier->queryPrepared($params['trans_type'], $params['gid']);
            return Result::SUCCESS;
        } catch (FailureException $throwable){
            return Result::FAILURE;
        }
    }
}

这个例子的调用本地方法是有问题的,会报一个"Call to a member function getStatusCode() on null"异常。
$this->barrier->call()这个组件应该是使用了类似guzzle方式调用本地事务

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants