38
38
import java .util .HashMap ;
39
39
import java .util .HashSet ;
40
40
import java .util .List ;
41
+ import java .util .Set ;
41
42
import java .util .concurrent .Executor ;
42
43
import java .util .concurrent .LinkedBlockingQueue ;
43
44
import java .util .concurrent .ThreadPoolExecutor ;
@@ -64,29 +65,6 @@ public Transaction(Datastore d) {
64
65
datastore = d ;
65
66
}
66
67
67
- private void recordVersion (MaybeDocument doc ) throws FirebaseFirestoreException {
68
- SnapshotVersion docVersion ;
69
- if (doc instanceof Document ) {
70
- docVersion = doc .getVersion ();
71
- } else if (doc instanceof NoDocument ) {
72
- // For nonexistent docs, we must use precondition with version 0 when we overwrite them.
73
- docVersion = SnapshotVersion .NONE ;
74
- } else {
75
- throw fail ("Unexpected document type in transaction: " + doc .getClass ().getCanonicalName ());
76
- }
77
-
78
- if (readVersions .containsKey (doc .getKey ())) {
79
- SnapshotVersion existingVersion = readVersions .get (doc .getKey ());
80
- if (!existingVersion .equals (doc .getVersion ())) {
81
- // This transaction will fail no matter what.
82
- throw new FirebaseFirestoreException (
83
- "Document version changed between two reads." , Code .ABORTED );
84
- }
85
- } else {
86
- readVersions .put (doc .getKey (), docVersion );
87
- }
88
- }
89
-
90
68
/**
91
69
* Takes a set of keys and asynchronously attempts to fetch all the documents from the backend,
92
70
* ignoring any local changes.
@@ -114,51 +92,6 @@ public Task<List<MaybeDocument>> lookup(List<DocumentKey> keys) {
114
92
});
115
93
}
116
94
117
- private void write (List <Mutation > mutations ) {
118
- ensureCommitNotCalled ();
119
- this .mutations .addAll (mutations );
120
- }
121
-
122
- /**
123
- * Returns version of this doc when it was read in this transaction as a precondition, or no
124
- * precondition if it was not read.
125
- */
126
- private Precondition precondition (DocumentKey key ) {
127
- @ Nullable SnapshotVersion version = readVersions .get (key );
128
- if (version != null ) {
129
- return Precondition .updateTime (version );
130
- } else {
131
- return Precondition .NONE ;
132
- }
133
- }
134
-
135
- /**
136
- * Returns the precondition for a document if the operation is an update, based on the provided
137
- * UpdateOptions.
138
- */
139
- private Precondition preconditionForUpdate (DocumentKey key ) throws FirebaseFirestoreException {
140
- @ Nullable SnapshotVersion version = this .readVersions .get (key );
141
- if (version != null && version .equals (SnapshotVersion .NONE )) {
142
- // The document to update doesn't exist, so fail the transaction.
143
- //
144
- // This has to be validated locally because you can't send a precondition that a document
145
- // does not exist without changing the semantics of the backend write to be an insert. This is
146
- // the reverse of what we want, since we want to assert that the document doesn't exist but
147
- // then send the update and have it fail. Since we can't express that to the backend, we have
148
- // to validate locally.
149
- //
150
- // Note: this can change once we can send separate verify writes in the transaction.
151
- throw new FirebaseFirestoreException (
152
- "Can't update a document that doesn't exist." , Code .INVALID_ARGUMENT );
153
- } else if (version != null ) {
154
- // Document exists, just base precondition on document update time.
155
- return Precondition .updateTime (version );
156
- } else {
157
- // Document was not read, so we just use the preconditions for a blind write.
158
- return Precondition .exists (true );
159
- }
160
- }
161
-
162
95
/** Stores a set mutation for the given key and value, to be committed when commit() is called. */
163
96
public void set (DocumentKey key , ParsedSetData data ) {
164
97
write (data .toMutationList (key , precondition (key )));
@@ -230,6 +163,74 @@ private static Executor createDefaultExecutor() {
230
163
return executor ;
231
164
}
232
165
166
+ private void recordVersion (MaybeDocument doc ) throws FirebaseFirestoreException {
167
+ SnapshotVersion docVersion ;
168
+ if (doc instanceof Document ) {
169
+ docVersion = doc .getVersion ();
170
+ } else if (doc instanceof NoDocument ) {
171
+ // For nonexistent docs, we must use precondition with version 0 when we overwrite them.
172
+ docVersion = SnapshotVersion .NONE ;
173
+ } else {
174
+ throw fail ("Unexpected document type in transaction: " + doc .getClass ().getCanonicalName ());
175
+ }
176
+
177
+ if (readVersions .containsKey (doc .getKey ())) {
178
+ SnapshotVersion existingVersion = readVersions .get (doc .getKey ());
179
+ if (!existingVersion .equals (doc .getVersion ())) {
180
+ // This transaction will fail no matter what.
181
+ throw new FirebaseFirestoreException (
182
+ "Document version changed between two reads." , Code .ABORTED );
183
+ }
184
+ } else {
185
+ readVersions .put (doc .getKey (), docVersion );
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Returns version of this doc when it was read in this transaction as a precondition, or no
191
+ * precondition if it was not read.
192
+ */
193
+ private Precondition precondition (DocumentKey key ) {
194
+ @ Nullable SnapshotVersion version = readVersions .get (key );
195
+ if (version != null ) {
196
+ return Precondition .updateTime (version );
197
+ } else {
198
+ return Precondition .NONE ;
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Returns the precondition for a document if the operation is an update, based on the provided
204
+ * UpdateOptions.
205
+ */
206
+ private Precondition preconditionForUpdate (DocumentKey key ) throws FirebaseFirestoreException {
207
+ @ Nullable SnapshotVersion version = this .readVersions .get (key );
208
+ if (version != null && version .equals (SnapshotVersion .NONE )) {
209
+ // The document to update doesn't exist, so fail the transaction.
210
+ //
211
+ // This has to be validated locally because you can't send a precondition that a document
212
+ // does not exist without changing the semantics of the backend write to be an insert. This is
213
+ // the reverse of what we want, since we want to assert that the document doesn't exist but
214
+ // then send the update and have it fail. Since we can't express that to the backend, we have
215
+ // to validate locally.
216
+ //
217
+ // Note: this can change once we can send separate verify writes in the transaction.
218
+ throw new FirebaseFirestoreException (
219
+ "Can't update a document that doesn't exist." , Code .INVALID_ARGUMENT );
220
+ } else if (version != null ) {
221
+ // Document exists, just base precondition on document update time.
222
+ return Precondition .updateTime (version );
223
+ } else {
224
+ // Document was not read, so we just use the preconditions for a blind write.
225
+ return Precondition .exists (true );
226
+ }
227
+ }
228
+
229
+ private void write (List <Mutation > mutations ) {
230
+ ensureCommitNotCalled ();
231
+ this .mutations .addAll (mutations );
232
+ }
233
+
233
234
private void ensureCommitNotCalled () {
234
235
hardAssert (
235
236
!committed ,
0 commit comments