@@ -67,6 +67,7 @@ import {
67
67
validateMinNumberOfArguments ,
68
68
validateObject ,
69
69
validateString ,
70
+ validateTimestamp ,
70
71
} from './validate' ;
71
72
import { WriteBatch } from './write-batch' ;
72
73
@@ -929,13 +930,37 @@ export class Firestore implements firestore.Firestore {
929
930
*
930
931
* @callback Firestore~updateFunction
931
932
* @template T
932
- * @param {Transaction } transaction The transaction object for this
933
+ * @param {Transaction } transaction The transaction object for this
933
934
* transaction.
934
935
* @returns {Promise<T> } The promise returned at the end of the transaction.
935
936
* This promise will be returned by {@link Firestore#runTransaction} if the
936
937
* transaction completed successfully.
937
938
*/
938
939
940
+ /**
941
+ * Options object for {@link Firestore#runTransaction} to configure a
942
+ * read-only transaction.
943
+ *
944
+ * @callback Firestore~ReadOnlyTransactionOptions
945
+ * @template T
946
+ * @param {true } readOnly Set to true to indicate a read-only transaction.
947
+ * @param {Timestamp= } readTime If specified, documents are read at the given
948
+ * time. This may not be more than 60 seconds in the past from when the
949
+ * request is processed by the server.
950
+ */
951
+
952
+ /**
953
+ * Options object for {@link Firestore#runTransaction} to configure a
954
+ * read-write transaction.
955
+ *
956
+ * @callback Firestore~ReadWriteTransactionOptions
957
+ * @template T
958
+ * @param {false= } readOnly Set to false or omit to indicate a read-write
959
+ * transaction.
960
+ * @param {number= } maxAttempts The maximum number of attempts for this
961
+ * transaction. Defaults to five.
962
+ */
963
+
939
964
/**
940
965
* Executes the given updateFunction and commits the changes applied within
941
966
* the transaction.
@@ -944,26 +969,33 @@ export class Firestore implements firestore.Firestore {
944
969
* modify Firestore documents under lock. You have to perform all reads before
945
970
* before you perform any write.
946
971
*
947
- * Documents read during a transaction are locked pessimistically. A
948
- * transaction's lock on a document blocks other transactions, batched
949
- * writes, and other non-transactional writes from changing that document.
950
- * A transaction releases its document locks at commit time or once it times
951
- * out or fails for any reason.
972
+ * Transactions can be performed as read-only or read-write transactions. By
973
+ * default, transactions are executed in read-write mode.
974
+ *
975
+ * A read-write transaction obtains a pessimistic lock on all documents that
976
+ * are read during the transaction. These locks block other transactions,
977
+ * batched writes, and other non-transactional writes from changing that
978
+ * document. Any writes in a read-write transactions are committed once
979
+ * 'updateFunction' resolves, which also releases all locks.
980
+ *
981
+ * If a read-write transaction fails with contention, the transaction is
982
+ * retried up to five times. The `updateFunction` is invoked once for each
983
+ * attempt.
952
984
*
953
- * Transactions are committed once 'updateFunction' resolves. If a transaction
954
- * fails with contention, the transaction is retried up to five times. The
955
- * `updateFunction` is invoked once for each attempt .
985
+ * Read-only transactions do not lock documents. They can be used to read
986
+ * documents at a consistent snapshot in time, which may be up to 60 seconds
987
+ * in the past. Read-only transactions are not retried .
956
988
*
957
989
* Transactions time out after 60 seconds if no documents are read.
958
990
* Transactions that are not committed within than 270 seconds are also
959
- * aborted.
991
+ * aborted. Any remaining locks are released when a transaction times out.
960
992
*
961
993
* @template T
962
994
* @param {Firestore~updateFunction } updateFunction The user function to
963
995
* execute within the transaction context.
964
- * @param {object= } transactionOptions Transaction options.
965
- * @param { number= } transactionOptions.maxAttempts - The maximum number of
966
- * attempts for this transaction .
996
+ * @param {
997
+ * Firestore~ReadWriteTransactionOptions|Firestore~ReadOnlyTransactionOptions=
998
+ * } transactionOptions Transaction options .
967
999
* @returns {Promise<T> } If the transaction completed successfully or was
968
1000
* explicitly aborted (by the updateFunction returning a failed Promise), the
969
1001
* Promise returned by the updateFunction will be returned here. Else if the
@@ -994,28 +1026,55 @@ export class Firestore implements firestore.Firestore {
994
1026
*/
995
1027
runTransaction < T > (
996
1028
updateFunction : ( transaction : Transaction ) => Promise < T > ,
997
- transactionOptions ?: { maxAttempts ?: number }
1029
+ transactionOptions ?:
1030
+ | firestore . ReadWriteTransactionOptions
1031
+ | firestore . ReadOnlyTransactionOptions
998
1032
) : Promise < T > {
999
1033
validateFunction ( 'updateFunction' , updateFunction ) ;
1000
1034
1001
1035
const tag = requestTag ( ) ;
1002
1036
1003
1037
let maxAttempts = DEFAULT_MAX_TRANSACTION_ATTEMPTS ;
1038
+ let readOnly = false ;
1039
+ let readTime : Timestamp | undefined ;
1004
1040
1005
1041
if ( transactionOptions ) {
1006
1042
validateObject ( 'transactionOptions' , transactionOptions ) ;
1007
- validateInteger (
1008
- 'transactionOptions.maxAttempts ' ,
1009
- transactionOptions . maxAttempts ,
1010
- { optional : true , minValue : 1 }
1043
+ validateBoolean (
1044
+ 'transactionOptions.readOnly ' ,
1045
+ transactionOptions . readOnly ,
1046
+ { optional : true }
1011
1047
) ;
1012
- maxAttempts =
1013
- transactionOptions . maxAttempts || DEFAULT_MAX_TRANSACTION_ATTEMPTS ;
1048
+
1049
+ if ( transactionOptions . readOnly ) {
1050
+ validateTimestamp (
1051
+ 'transactionOptions.readTime' ,
1052
+ transactionOptions . readTime ,
1053
+ { optional : true }
1054
+ ) ;
1055
+
1056
+ readOnly = true ;
1057
+ readTime = transactionOptions . readTime as Timestamp | undefined ;
1058
+ maxAttempts = 1 ;
1059
+ } else {
1060
+ validateInteger (
1061
+ 'transactionOptions.maxAttempts' ,
1062
+ transactionOptions . maxAttempts ,
1063
+ { optional : true , minValue : 1 }
1064
+ ) ;
1065
+
1066
+ maxAttempts =
1067
+ transactionOptions . maxAttempts || DEFAULT_MAX_TRANSACTION_ATTEMPTS ;
1068
+ }
1014
1069
}
1015
1070
1016
1071
const transaction = new Transaction ( this , tag ) ;
1017
1072
return this . initializeIfNeeded ( tag ) . then ( ( ) =>
1018
- transaction . runTransaction ( updateFunction , maxAttempts )
1073
+ transaction . runTransaction ( updateFunction , {
1074
+ maxAttempts,
1075
+ readOnly,
1076
+ readTime,
1077
+ } )
1019
1078
) ;
1020
1079
}
1021
1080
0 commit comments