@@ -30,6 +30,7 @@ import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence';
30
30
import {
31
31
DbCollectionParent ,
32
32
DbDocumentMutation ,
33
+ DbDocumentOverlay ,
33
34
DbMutationBatch ,
34
35
DbMutationQueue ,
35
36
DbPrimaryClient ,
@@ -52,6 +53,8 @@ import {
52
53
DbDocumentMutationKey ,
53
54
DbDocumentMutationPlaceholder ,
54
55
DbDocumentMutationStore ,
56
+ DbDocumentOverlayKey ,
57
+ DbDocumentOverlayStore ,
55
58
DbMutationBatchKey ,
56
59
DbMutationBatchStore ,
57
60
DbMutationQueueKey ,
@@ -81,6 +84,7 @@ import {
81
84
import {
82
85
fromDbTarget ,
83
86
LocalSerializer ,
87
+ toDbDocumentOverlayKey ,
84
88
toDbRemoteDocument ,
85
89
toDbTarget ,
86
90
toDbTimestamp ,
@@ -92,6 +96,7 @@ import { ClientId } from '../../../src/local/shared_client_state';
92
96
import { SimpleDb , SimpleDbTransaction } from '../../../src/local/simple_db' ;
93
97
import { TargetData , TargetPurpose } from '../../../src/local/target_data' ;
94
98
import { MutableDocument } from '../../../src/model/document' ;
99
+ import { DocumentKey } from '../../../src/model/document_key' ;
95
100
import { getWindow } from '../../../src/platform/dom' ;
96
101
import { firestoreV1ApiClientInterfaces } from '../../../src/protos/firestore_proto_api' ;
97
102
import {
@@ -1044,6 +1049,214 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => {
1044
1049
} ) ;
1045
1050
} ) ;
1046
1051
1052
+ it ( 'can upgrade from schema version 13 to 14 (overlay migration)' , function ( this : Context ) {
1053
+ // This test creates a database with schema version 13 that has three users,
1054
+ // two of whom have local mutations.
1055
+ const testWriteFoo = {
1056
+ update : {
1057
+ name : 'projects/test-project/databases/(default)/documents/docs/foo' ,
1058
+ fields : { }
1059
+ }
1060
+ } ;
1061
+ const testWriteBar = {
1062
+ update : {
1063
+ name : 'projects/test-project/databases/(default)/documents/docs/bar' ,
1064
+ fields : { }
1065
+ }
1066
+ } ;
1067
+ const testWriteBaz = {
1068
+ update : {
1069
+ name : 'projects/test-project/databases/(default)/documents/docs/baz' ,
1070
+ fields : { }
1071
+ }
1072
+ } ;
1073
+ const testWritePending = {
1074
+ update : {
1075
+ name : 'projects/test-project/databases/(default)/documents/docs/pending' ,
1076
+ fields : { }
1077
+ }
1078
+ } ;
1079
+ const testMutations : DbMutationBatch [ ] = [
1080
+ {
1081
+ userId : 'user1' ,
1082
+ batchId : 1 ,
1083
+ localWriteTimeMs : 1337 ,
1084
+ baseMutations : undefined ,
1085
+ mutations : [ testWriteFoo ]
1086
+ } ,
1087
+ {
1088
+ userId : 'user1' ,
1089
+ batchId : 2 ,
1090
+ localWriteTimeMs : 1337 ,
1091
+ baseMutations : undefined ,
1092
+ mutations : [ testWriteFoo ]
1093
+ } ,
1094
+ {
1095
+ userId : 'user2' ,
1096
+ batchId : 3 ,
1097
+ localWriteTimeMs : 1337 ,
1098
+ baseMutations : undefined ,
1099
+ mutations : [ testWriteBar , testWriteBaz ]
1100
+ } ,
1101
+ {
1102
+ userId : 'user2' ,
1103
+ batchId : 4 ,
1104
+ localWriteTimeMs : 1337 ,
1105
+ baseMutations : undefined ,
1106
+ mutations : [ testWritePending ]
1107
+ } ,
1108
+ {
1109
+ userId : 'user1' ,
1110
+ batchId : 5 ,
1111
+ localWriteTimeMs : 1337 ,
1112
+ baseMutations : undefined ,
1113
+ mutations : [ testWritePending ]
1114
+ }
1115
+ ] ;
1116
+
1117
+ return withDb ( 13 , db => {
1118
+ return db . runTransaction (
1119
+ this . test ! . fullTitle ( ) ,
1120
+ 'readwrite' ,
1121
+ V13_STORES ,
1122
+ txn => {
1123
+ const mutationBatchStore = txn . store <
1124
+ DbMutationBatchKey ,
1125
+ DbMutationBatch
1126
+ > ( DbMutationBatchStore ) ;
1127
+ const documentMutationStore = txn . store <
1128
+ DbDocumentMutationKey ,
1129
+ DbDocumentMutation
1130
+ > ( DbDocumentMutationStore ) ;
1131
+ const mutationQueuesStore = txn . store <
1132
+ DbMutationQueueKey ,
1133
+ DbMutationQueue
1134
+ > ( DbMutationQueueStore ) ;
1135
+ // Manually populate the mutation queue and create all indicies.
1136
+ return PersistencePromise . forEach (
1137
+ testMutations ,
1138
+ ( testMutation : DbMutationBatch ) => {
1139
+ return mutationBatchStore . put ( testMutation ) . next ( ( ) => {
1140
+ return PersistencePromise . forEach (
1141
+ testMutation . mutations ,
1142
+ ( write : firestoreV1ApiClientInterfaces . Write ) => {
1143
+ const indexKey = newDbDocumentMutationKey (
1144
+ testMutation . userId ,
1145
+ path ( write . update ! . name ! , 5 ) ,
1146
+ testMutation . batchId
1147
+ ) ;
1148
+ return documentMutationStore . put (
1149
+ indexKey ,
1150
+ DbDocumentMutationPlaceholder
1151
+ ) ;
1152
+ }
1153
+ ) ;
1154
+ } ) ;
1155
+ }
1156
+ ) . next ( ( ) =>
1157
+ // Populate the mutation queues' metadata
1158
+ PersistencePromise . waitFor ( [
1159
+ mutationQueuesStore . put ( {
1160
+ userId : 'user1' ,
1161
+ lastAcknowledgedBatchId : - 1 ,
1162
+ lastStreamToken : ''
1163
+ } ) ,
1164
+ mutationQueuesStore . put ( {
1165
+ userId : 'user2' ,
1166
+ lastAcknowledgedBatchId : - 1 ,
1167
+ lastStreamToken : ''
1168
+ } ) ,
1169
+ mutationQueuesStore . put ( {
1170
+ userId : 'user3' ,
1171
+ lastAcknowledgedBatchId : - 1 ,
1172
+ lastStreamToken : ''
1173
+ } )
1174
+ ] )
1175
+ ) ;
1176
+ }
1177
+ ) ;
1178
+ } ) . then ( ( ) =>
1179
+ withDb ( 14 , ( db , version ) => {
1180
+ expect ( version ) . to . be . equal ( 14 ) ;
1181
+
1182
+ return db . runTransaction (
1183
+ this . test ! . fullTitle ( ) ,
1184
+ 'readwrite' ,
1185
+ V14_STORES ,
1186
+ txn => {
1187
+ const documentOverlayStore = txn . store <
1188
+ DbDocumentOverlayKey ,
1189
+ DbDocumentOverlay
1190
+ > ( DbDocumentOverlayStore ) ;
1191
+
1192
+ // We should have a total of 5 overlays:
1193
+ // For user1: testWriteFoo, and testWritePending
1194
+ // For user2: testWriteBar, testWriteBaz, and testWritePending
1195
+ // For user3: NO OVERLAYS!
1196
+ let p = documentOverlayStore . count ( ) . next ( count => {
1197
+ expect ( count ) . to . equal ( 5 ) ;
1198
+ } ) ;
1199
+ p = p . next ( ( ) => {
1200
+ const key = toDbDocumentOverlayKey (
1201
+ 'user1' ,
1202
+ DocumentKey . fromPath ( 'docs/foo' )
1203
+ ) ;
1204
+ return documentOverlayStore . get ( key ) . next ( overlay => {
1205
+ expect ( overlay ) . to . not . be . null ;
1206
+ expect ( overlay ! . overlayMutation ) . to . deep . equal ( testWriteFoo ) ;
1207
+ } ) ;
1208
+ } ) ;
1209
+ p = p . next ( ( ) => {
1210
+ const key = toDbDocumentOverlayKey (
1211
+ 'user1' ,
1212
+ DocumentKey . fromPath ( 'docs/pending' )
1213
+ ) ;
1214
+ return documentOverlayStore . get ( key ) . next ( overlay => {
1215
+ expect ( overlay ) . to . not . be . null ;
1216
+ expect ( overlay ! . overlayMutation ) . to . deep . equal (
1217
+ testWritePending
1218
+ ) ;
1219
+ } ) ;
1220
+ } ) ;
1221
+ p = p . next ( ( ) => {
1222
+ const key = toDbDocumentOverlayKey (
1223
+ 'user2' ,
1224
+ DocumentKey . fromPath ( 'docs/bar' )
1225
+ ) ;
1226
+ return documentOverlayStore . get ( key ) . next ( overlay => {
1227
+ expect ( overlay ) . to . not . be . null ;
1228
+ expect ( overlay ! . overlayMutation ) . to . deep . equal ( testWriteBar ) ;
1229
+ } ) ;
1230
+ } ) ;
1231
+ p = p . next ( ( ) => {
1232
+ const key = toDbDocumentOverlayKey (
1233
+ 'user2' ,
1234
+ DocumentKey . fromPath ( 'docs/baz' )
1235
+ ) ;
1236
+ return documentOverlayStore . get ( key ) . next ( overlay => {
1237
+ expect ( overlay ) . to . not . be . null ;
1238
+ expect ( overlay ! . overlayMutation ) . to . deep . equal ( testWriteBaz ) ;
1239
+ } ) ;
1240
+ } ) ;
1241
+ p = p . next ( ( ) => {
1242
+ const key = toDbDocumentOverlayKey (
1243
+ 'user2' ,
1244
+ DocumentKey . fromPath ( 'docs/pending' )
1245
+ ) ;
1246
+ return documentOverlayStore . get ( key ) . next ( overlay => {
1247
+ expect ( overlay ) . to . not . be . null ;
1248
+ expect ( overlay ! . overlayMutation ) . to . deep . equal (
1249
+ testWritePending
1250
+ ) ;
1251
+ } ) ;
1252
+ } ) ;
1253
+ return p ;
1254
+ }
1255
+ ) ;
1256
+ } )
1257
+ ) ;
1258
+ } ) ;
1259
+
1047
1260
it ( 'can upgrade from version 13 to 14' , async ( ) => {
1048
1261
await withDb ( 13 , async ( ) => { } ) ;
1049
1262
await withDb ( 14 , async ( db , version , objectStores ) => {
0 commit comments