关于在Laravel 中支持Mongo事务的一些问题

在GitHub上面看到了这么一个 PR ,看了一下代码似乎不能够通过测试用例。 但是实际上的CI构建日志却显示全部通过。希望大佬给予解答。关键代码会在文章下方给出,文章也附有GitHub源码链接,希望大家帮我看看。

关于在Laravel 中支持Mongo事务的一些问题
主要我有疑问的是这个 tests/TransactionTest.php 测试用例的testTransaction 这个测试。 Diff信息链接 根据 Laravel 源码中 src/Illuminate/Database/Concerns/ManagesTransactions.php ManagesTransactions.php#L44第44行的代码,想要事务能够成功执行 $this->transactions 的值一定要是 1 。而扩展的代码重写了beginTransaction这个函数,那么原本115行的 $this->transactions++; 就没有被执行到,导致 44 行的判断 if ($this->transactions == 1) 就不可能成立事务不会被执行。

Laravel 中的 beginTransaction

/**
 * Execute a Closure within a transaction. * * @param \Closure $callback
  * @param int $attempts
  * @return mixed
 * * @throws \Throwable
 */
 public function transaction(Closure $callback, $attempts = 1)
{
  for ($currentAttempt = 1; $currentAttempt <= $attempts; $currentAttempt++) {
  $this->beginTransaction();

  // We'll simply execute the given callback within a try / catch block and if we
 // catch any exception we can rollback this transaction so that none of this // gets actually persisted to a database or stored in a permanent fashion.  try {
  $callbackResult = $callback($this);
  }

  // If we catch an exception we'll rollback this transaction and try again if we
 // are not out of attempts. If we are out of attempts we will just throw the // exception back out and let the developer handle an uncaught exceptions.  catch (Throwable $e) {
  $this->handleTransactionException(
  $e, $currentAttempt, $attempts
  );

 continue;  }

  try {
  if ($this->transactions == 1) {     // 44行
  $this->getPdo()->commit();

  optional($this->transactionsManager)->commit($this->getName());
  }

  $this->transactions = max(0, $this->transactions - 1);
  } catch (Throwable $e) {
  $this->handleCommitTransactionException(
  $e, $currentAttempt, $attempts
  );

 continue;  }

  $this->fireConnectionEvent('committed');

 return $callbackResult;
  }
}

.....

/**
 * Start a new database transaction.
 *
 * @return void
 *
 * @throws \Throwable
 */
public function beginTransaction()
{
    $this->createTransaction();

    $this->transactions++;    // 115行

    optional($this->transactionsManager)->begin(
        $this->getName(), $this->transactions
    );

    $this->fireConnectionEvent('beganTransaction');
}

扩展中的 beginTransaction

public function beginTransaction()
{
    $this->session_key = uniqid();
    $this->sessions[$this->session_key] = $this->connection->startSession();

    $this->sessions[$this->session_key]->startTransaction([
        'readPreference' => new ReadPreference(ReadPreference::RP_PRIMARY),
        'writeConcern' => new WriteConcern(1),
        'readConcern' => new ReadConcern(ReadConcern::LOCAL)
    ]);
}

扩展中的测试用例。

public function testTransaction()
 {
     $count = DB::collection('users')->count();
     $this->assertEquals(1, $count);

     $new_age = $this->originData['age'] + 1;
     DB::transaction(function () use ($new_age) {
         DB::collection('users')->insert($this->insertData);
         DB::collection('users')->where('name', $this->originData['name'])->update(['age' => $new_age]);
     });
     $count = DB::collection('users')->count();
     $this->assertEquals(2, $count);

     $checkInsert = DB::collection('users')->where('name', $this->insertData['name'])->first();
     $this->assertNotNull($checkInsert);
     $this->assertEquals($this->insertData['age'], $checkInsert['age']);

     $checkUpdate = DB::collection('users')->where('name', $this->originData['name'])->first();
     $this->assertEquals($new_age, $checkUpdate['age']);
 }
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!