@@ -326,6 +326,7 @@ export class MockSpanner {
326326 protobuf . Session
327327 > ( ) ;
328328 private mutationOnly : boolean ;
329+ private transactionSeqNum : Map < string , number > = new Map < string , number > ( ) ;
329330 private transactionCounters : Map < string , number > = new Map < string , number > ( ) ;
330331 private transactions : Map < string , protobuf . Transaction > = new Map <
331332 string ,
@@ -679,10 +680,12 @@ export class MockSpanner {
679680 this . pushRequest ( call . request ! , call . metadata ) ;
680681 this . simulateExecutionTime ( this . executeStreamingSql . name )
681682 . then ( ( ) => {
683+ let transactionKey ;
682684 if ( call . request ! . transaction ) {
683685 const fullTransactionId = `${ call . request ! . session } /transactions/${
684686 call . request ! . transaction . id
685687 } `;
688+ transactionKey = fullTransactionId ;
686689 if ( this . abortedTransactions . has ( fullTransactionId ) ) {
687690 call . sendMetadata ( new Metadata ( ) ) ;
688691 call . emit (
@@ -701,29 +704,37 @@ export class MockSpanner {
701704 call . request ! . session ,
702705 call . request ! . transaction . begin ,
703706 ) ;
704- const precommitToken = session ?. multiplexed
705- ? protobuf . MultiplexedSessionPrecommitToken . create ( {
706- precommitToken : Buffer . from ( 'mock-precommit-token' ) ,
707- seqNum : randomInt ( 1 , 1000 ) ,
708- } )
709- : null ;
710707 if ( txn instanceof Error ) {
711708 call . sendMetadata ( new Metadata ( ) ) ;
712709 call . emit ( 'error' , txn ) ;
713710 call . end ( ) ;
714711 return ;
715712 }
713+ transactionKey = `${ call . request ! . session } /transactions/${ txn . id . toString ( ) } ` ;
716714 if ( res . type === StatementResultType . RESULT_SET ) {
717715 ( res . resultSet as protobuf . ResultSet ) . metadata ! . transaction = txn ;
718- ( res . resultSet as protobuf . ResultSet ) . precommitToken =
719- precommitToken ;
720716 }
721717 }
718+
719+ // get the current seqNum
720+ const currentSeqNum = this . transactionSeqNum . get ( transactionKey ) || 0 ;
721+ const nextSeqNum = currentSeqNum + 1 ;
722+
723+ // set the next seqNum
724+ this . transactionSeqNum . set ( transactionKey , nextSeqNum ) ;
725+ const precommitToken = session ?. multiplexed
726+ ? protobuf . MultiplexedSessionPrecommitToken . create ( {
727+ precommitToken : Buffer . from ( 'mock-precommit-token' ) ,
728+ seqNum : nextSeqNum ,
729+ } )
730+ : null ;
722731 let partialResultSets ;
723732 let resumeIndex ;
724733 let streamErr ;
725734 switch ( res . type ) {
726735 case StatementResultType . RESULT_SET :
736+ ( res . resultSet as protobuf . ResultSet ) . precommitToken =
737+ precommitToken ;
727738 if ( Array . isArray ( res . resultSet ) ) {
728739 partialResultSets = res . resultSet ;
729740 } else {
@@ -758,6 +769,7 @@ export class MockSpanner {
758769 case StatementResultType . UPDATE_COUNT :
759770 call . write (
760771 MockSpanner . emptyPartialResultSet (
772+ precommitToken ,
761773 Buffer . from ( '1' . padStart ( 8 , '0' ) ) ,
762774 ) ,
763775 ) ;
@@ -770,7 +782,9 @@ export class MockSpanner {
770782 call . emit ( 'error' , streamErr ) ;
771783 break ;
772784 }
773- call . write ( MockSpanner . toPartialResultSet ( res . updateCount ) ) ;
785+ call . write (
786+ MockSpanner . toPartialResultSet ( precommitToken , res . updateCount ) ,
787+ ) ;
774788 break ;
775789 case StatementResultType . ERROR :
776790 call . sendMetadata ( new Metadata ( ) ) ;
@@ -816,6 +830,7 @@ export class MockSpanner {
816830 const partial = protobuf . PartialResultSet . create ( {
817831 resumeToken : Buffer . from ( token ) ,
818832 values : [ ] ,
833+ precommitToken : resultSet . precommitToken ,
819834 } ) ;
820835 for (
821836 let row = i ;
@@ -841,14 +856,23 @@ export class MockSpanner {
841856 }
842857
843858 private static emptyPartialResultSet (
859+ precommitToken :
860+ | protobuf . IMultiplexedSessionPrecommitToken
861+ | null
862+ | undefined ,
844863 resumeToken : Uint8Array ,
845864 ) : protobuf . PartialResultSet {
846865 return protobuf . PartialResultSet . create ( {
847866 resumeToken,
867+ precommitToken : precommitToken ,
848868 } ) ;
849869 }
850870
851871 private static toPartialResultSet (
872+ precommitToken :
873+ | protobuf . IMultiplexedSessionPrecommitToken
874+ | null
875+ | undefined ,
852876 rowCount : number ,
853877 ) : protobuf . PartialResultSet {
854878 const stats = {
@@ -857,6 +881,7 @@ export class MockSpanner {
857881 } ;
858882 return protobuf . PartialResultSet . create ( {
859883 stats,
884+ precommitToken : precommitToken ,
860885 } ) ;
861886 }
862887
@@ -992,10 +1017,12 @@ export class MockSpanner {
9921017
9931018 this . simulateExecutionTime ( this . streamingRead . name )
9941019 . then ( ( ) => {
1020+ let transactionKey ;
9951021 if ( call . request ! . transaction ) {
9961022 const fullTransactionId = `${ call . request ! . session } /transactions/${
9971023 call . request ! . transaction . id
9981024 } `;
1025+ transactionKey = fullTransactionId ;
9991026 if ( this . abortedTransactions . has ( fullTransactionId ) ) {
10001027 call . sendMetadata ( new Metadata ( ) ) ;
10011028 call . emit (
@@ -1019,29 +1046,37 @@ export class MockSpanner {
10191046 call . request ! . session ,
10201047 call . request ! . transaction . begin ,
10211048 ) ;
1022- const precommitToken = session ?. multiplexed
1023- ? protobuf . MultiplexedSessionPrecommitToken . create ( {
1024- precommitToken : Buffer . from ( 'mock-precommit-token' ) ,
1025- seqNum : randomInt ( 1 , 1000 ) ,
1026- } )
1027- : null ;
10281049 if ( txn instanceof Error ) {
10291050 call . sendMetadata ( new Metadata ( ) ) ;
10301051 call . emit ( 'error' , txn ) ;
10311052 call . end ( ) ;
10321053 return ;
10331054 }
1055+ transactionKey = `${ call . request ! . session } /transactions/${ txn . id . toString ( ) } ` ;
10341056 if ( res . type === ReadRequestResultType . RESULT_SET ) {
10351057 call . sendMetadata ( new Metadata ( ) ) ;
10361058 ( res . resultSet as protobuf . ResultSet ) . metadata ! . transaction = txn ;
1037- ( res . resultSet as protobuf . ResultSet ) . precommitToken =
1038- precommitToken ;
10391059 }
10401060 }
1061+
1062+ // get the current seqNum
1063+ const currentSeqNum = this . transactionSeqNum . get ( transactionKey ) || 0 ;
1064+ const nextSeqNum = currentSeqNum + 1 ;
1065+
1066+ // set the next SeqNum
1067+ this . transactionSeqNum . set ( transactionKey , nextSeqNum ) ;
1068+ const precommitToken = session ?. multiplexed
1069+ ? protobuf . MultiplexedSessionPrecommitToken . create ( {
1070+ precommitToken : Buffer . from ( 'mock-precommit-token' ) ,
1071+ seqNum : nextSeqNum ,
1072+ } )
1073+ : null ;
10411074 let partialResultSets ;
10421075 let resumeIndex ;
10431076 switch ( res . type ) {
10441077 case ReadRequestResultType . RESULT_SET :
1078+ ( res . resultSet as protobuf . ResultSet ) . precommitToken =
1079+ precommitToken ;
10451080 if ( Array . isArray ( res . resultSet ) ) {
10461081 partialResultSets = res . resultSet ;
10471082 } else {
@@ -1153,6 +1188,10 @@ export class MockSpanner {
11531188 session . name + '/transactions/' + transactionId ;
11541189 const transaction = this . transactions . get ( fullTransactionId ) ;
11551190 if ( transaction ) {
1191+ // unique transaction key
1192+ const transactionKey = `${ call . request . session } /transactions/${ call . request . transactionId } ` ;
1193+ // delete the transaction key
1194+ this . transactionSeqNum . delete ( transactionKey ) ;
11561195 this . transactions . delete ( fullTransactionId ) ;
11571196 this . transactionOptions . delete ( fullTransactionId ) ;
11581197 callback (
@@ -1197,6 +1236,10 @@ export class MockSpanner {
11971236 const fullTransactionId = session . name + '/transactions/' + transactionId ;
11981237 const transaction = this . transactions . get ( fullTransactionId ) ;
11991238 if ( transaction ) {
1239+ // unique transaction key
1240+ const transactionKey = `${ call . request . session } /transactions/${ call . request . transactionId } ` ;
1241+ // delete the key
1242+ this . transactionSeqNum . delete ( transactionKey ) ;
12001243 this . transactions . delete ( fullTransactionId ) ;
12011244 this . transactionOptions . delete ( fullTransactionId ) ;
12021245 callback ( null , google . protobuf . Empty . create ( ) ) ;
@@ -1273,13 +1316,18 @@ export class MockSpanner {
12731316 const transactionId = id . toString ( ) . padStart ( 12 , '0' ) ;
12741317 const fullTransactionId = session . name + '/transactions/' + transactionId ;
12751318 const readTimestamp = options && options . readOnly ? now ( ) : undefined ;
1276- const precommitToken =
1277- this . mutationOnly && session . multiplexed && options ?. readWrite
1278- ? {
1279- precommitToken : Buffer . from ( 'mock-precommit-token' ) ,
1280- seqNum : randomInt ( 1 , 1000 ) ,
1281- }
1282- : null ;
1319+ let precommitToken ;
1320+ if ( this . mutationOnly && session . multiplexed && options ?. readWrite ) {
1321+ // get the current seqNum
1322+ const currentSeqNum = this . transactionSeqNum . get ( fullTransactionId ) || 0 ;
1323+ const nextSeqNum = currentSeqNum + 1 ;
1324+ // set the next seqNum
1325+ this . transactionSeqNum . set ( fullTransactionId , nextSeqNum ) ;
1326+ precommitToken = {
1327+ precommitToken : Buffer . from ( 'mock-precommit-token' ) ,
1328+ seqNum : nextSeqNum ,
1329+ } ;
1330+ }
12831331 const transaction = protobuf . Transaction . create ( {
12841332 id : Buffer . from ( transactionId ) ,
12851333 readTimestamp,
0 commit comments