Skip to content

Commit 7aa8b07

Browse files
authored
fix(Spanner): ensure precommit token is set for ILB transactions (#9406)
1 parent be0d240 commit 7aa8b07

4 files changed

Lines changed: 79 additions & 1 deletion

File tree

Spanner/src/Operation.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ public function transaction(SessionCache $session, array $options = []): Transac
736736
'requestOptions' => $beginTransaction->getRequestOptions(),
737737
'transactionOptions' => $txnOptions,
738738
]);
739-
return new Transaction(
739+
$transaction = new Transaction(
740740
$this,
741741
$session,
742742
$id,

Spanner/src/Transaction.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,9 @@ public function commit(array $options = []): Timestamp
476476
$transaction = $this->operation->transaction($this->session, $operationTransactionOptions);
477477
// Set the transaction ID of the current transaction.
478478
$this->transactionId = $transaction->id();
479+
if (isset($transaction->precommitToken)) {
480+
$this->setPrecommitToken($transaction->precommitToken);
481+
}
479482
}
480483

481484
if (!$this->singleUseState()) {

Spanner/tests/Unit/OperationTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,30 @@ public function testTransactionWithExcludeTxnFromChangeStreams()
490490
$this->assertEquals('foo', $transaction->id());
491491
}
492492

493+
public function testTransactionWithPrecommitToken()
494+
{
495+
$precommitToken = new MultiplexedSessionPrecommitToken([
496+
'precommit_token' => 'my-precommit-token',
497+
]);
498+
$this->spannerClient->beginTransaction(
499+
Argument::cetera()
500+
)
501+
->shouldBeCalled()
502+
->willReturn(new TransactionProto([
503+
'id' => self::TRANSACTION,
504+
'precommit_token' => $precommitToken,
505+
]));
506+
507+
$t = $this->operation->transaction($this->session);
508+
$this->assertInstanceOf(Transaction::class, $t);
509+
$this->assertEquals(self::TRANSACTION, $t->id());
510+
511+
$ref = new \ReflectionClass(Transaction::class);
512+
$prop = $ref->getProperty('precommitToken');
513+
$this->assertNotNull($prop->getValue($t));
514+
$this->assertEquals($precommitToken, $prop->getValue($t));
515+
}
516+
493517
public function testExecuteAndExecuteUpdateWithExcludeTxnFromChangeStreams()
494518
{
495519
$sql = 'SELECT example FROM sql_query';

Spanner/tests/Unit/TransactionTest.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,57 @@ public function testCommitWithMaxCommitDelay()
620620
$this->assertEquals(1, $transaction->getCommitStats()->getMutationCount());
621621
}
622622

623+
public function testCommitSetsPrecommitTokenFromInlineBegin()
624+
{
625+
$precommitToken = new MultiplexedSessionPrecommitToken([
626+
'precommit_token' => 'my-precommit-token',
627+
]);
628+
629+
$operation = $this->prophesize(Operation::class);
630+
631+
// Create the transaction returned by Operation::transaction()
632+
$returnedTransaction = new Transaction(
633+
$operation->reveal(),
634+
$this->session->reveal(),
635+
self::TRANSACTION,
636+
[]
637+
);
638+
$returnedTransaction->setPrecommitToken($precommitToken);
639+
640+
$operation->transaction($this->session->reveal(), Argument::any())
641+
->shouldBeCalled()
642+
->willReturn($returnedTransaction);
643+
644+
// Verify that commit() receives the precommit token in options
645+
$operation->commit(
646+
$this->session->reveal(),
647+
Argument::any(),
648+
Argument::that(function ($options) use ($precommitToken) {
649+
$this->assertArrayHasKey('precommitToken', $options);
650+
$this->assertEquals($precommitToken, $options['precommitToken']);
651+
return true;
652+
})
653+
)
654+
->shouldBeCalled()
655+
->willReturn($this->commitResponseWithCommitStats());
656+
657+
$transaction = new Transaction(
658+
$operation->reveal(),
659+
$this->session->reveal(),
660+
null, // Null transaction ID to trigger inline begin
661+
[
662+
'begin' => ['readWrite' => []]
663+
]
664+
);
665+
666+
$transaction->insert('Posts', ['foo' => 'bar']);
667+
$transaction->commit();
668+
669+
$ref = new \ReflectionClass(Transaction::class);
670+
$prop = $ref->getProperty('precommitToken');
671+
$this->assertNull($prop->getValue($transaction));
672+
}
673+
623674
public function testCommitInvalidState()
624675
{
625676
$this->expectException(\BadMethodCallException::class);

0 commit comments

Comments
 (0)