@@ -8,7 +8,7 @@ import { FirestoreBackfillOptions } from "./types";
8
8
export const handlerFromProcess =
9
9
( process : Process , options : FirestoreBackfillOptions ) =>
10
10
async ( chunk : string [ ] ) => {
11
- // get documents from firestore
11
+ // Get documents from Firestore
12
12
const docs = await getValidDocs ( process , chunk , options ) ;
13
13
14
14
if ( docs . length === 0 ) {
@@ -19,8 +19,16 @@ export const handlerFromProcess =
19
19
functions . logger . info ( `Handling ${ docs . length } documents` ) ;
20
20
21
21
if ( docs . length === 1 ) {
22
- // TODO: get rid of ! assertion
23
- const result = await process . processFn ( docs [ 0 ] . data ( ) ! ) ;
22
+ const data = docs [ 0 ] . data ( ) ;
23
+
24
+ if ( ! data ) {
25
+ functions . logger . error (
26
+ `Document ${ docs [ 0 ] . ref . path } does not have any data`
27
+ ) ;
28
+ return { success : 0 } ;
29
+ }
30
+
31
+ const result = await process . processFn ( data ) ;
24
32
25
33
try {
26
34
await admin
@@ -41,33 +49,50 @@ export const handlerFromProcess =
41
49
}
42
50
43
51
const batches = chunkArray ( docs , 50 ) ;
52
+ let successCount = 0 ;
44
53
45
54
const results = await Promise . all (
46
55
batches . map ( async ( batch ) => {
47
- // TODO: get rid of ! assertion
48
- return process . batchProcess ( batch . map ( ( doc ) => doc . data ( ) ! ) ) ;
56
+ const batchData = batch
57
+ . map ( ( doc ) => {
58
+ const data = doc . data ( ) ;
59
+ if ( ! data ) {
60
+ functions . logger . warn ( `Document ${ doc . ref . path } has no data` ) ;
61
+ return null ;
62
+ }
63
+ return data ;
64
+ } )
65
+ . filter ( ( data ) => data !== null ) ;
66
+
67
+ return process . batchProcess ( batchData ) ;
49
68
} )
50
69
) ;
51
70
52
71
const toWrite = results . flat ( ) ;
53
72
const writer = admin . firestore ( ) . batch ( ) ;
54
73
55
74
for ( let i = 0 ; i < toWrite . length ; i ++ ) {
56
- writer . update (
57
- admin . firestore ( ) . collection ( options . collectionName ) . doc ( docs [ i ] . id ) ,
58
- {
59
- ...toWrite [ 0 ] ,
60
- [ `status.${ process . id } .state` ] : "BACKFILLED" ,
61
- [ `status.${ process . id } .completeTime` ] :
62
- admin . firestore . FieldValue . serverTimestamp ( ) ,
63
- }
64
- ) ;
75
+ try {
76
+ writer . update (
77
+ admin . firestore ( ) . collection ( options . collectionName ) . doc ( docs [ i ] . id ) ,
78
+ {
79
+ ...toWrite [ i ] ,
80
+ [ `status.${ process . id } .state` ] : "BACKFILLED" ,
81
+ [ `status.${ process . id } .completeTime` ] :
82
+ admin . firestore . FieldValue . serverTimestamp ( ) ,
83
+ }
84
+ ) ;
85
+ successCount ++ ;
86
+ } catch ( e ) {
87
+ functions . logger . error ( `Failed to update document ${ docs [ i ] . id } : ${ e } ` ) ;
88
+ }
65
89
}
90
+
66
91
await writer . commit ( ) ;
67
92
68
93
functions . logger . info ( `Completed processing ${ docs . length } documents` ) ;
69
94
70
- return { success : docs . length } ;
95
+ return { success : successCount } ;
71
96
} ;
72
97
73
98
export async function getValidDocs (
@@ -78,24 +103,24 @@ export async function getValidDocs(
78
103
const documents : DocumentSnapshot [ ] = [ ] ;
79
104
80
105
await admin . firestore ( ) . runTransaction ( async ( transaction ) => {
81
- const refs = documentIds . map ( ( id : string ) =>
106
+ const refs = documentIds . map ( ( id ) =>
82
107
admin . firestore ( ) . collection ( options . collectionName ) . doc ( id )
83
108
) ;
84
- //@ts -ignore
85
- const docs = await transaction . getAll < DocumentData > ( ...refs ) ;
109
+ const docs = await transaction . getAll ( ...refs ) ;
86
110
87
111
for ( const doc of docs ) {
88
112
const data = doc . data ( ) ;
89
- if ( ! process . shouldBackfill || ! process . shouldBackfill ( data ) ) {
113
+ if ( ! data ) {
114
+ functions . logger . warn ( `Document ${ doc . ref . path } has no data` ) ;
115
+ } else if ( ! process . shouldBackfill || ! process . shouldBackfill ( data ) ) {
90
116
functions . logger . warn (
91
117
`Document ${ doc . ref . path } is not valid for ${ process . id } process`
92
118
) ;
93
119
} else if (
94
- // TODO: add a param for backfill strategy
95
- data [ "status" ] &&
96
- data [ "status" ] [ process . id ] &&
97
- data [ "status" ] [ process . id ] [ "state" ] &&
98
- data [ "status" ] [ process . id ] . state !== "BACKFILLED"
120
+ data . status &&
121
+ data . status [ process . id ] &&
122
+ data . status [ process . id ] . state &&
123
+ data . status [ process . id ] . state !== "BACKFILLED"
99
124
) {
100
125
functions . logger . warn (
101
126
`Document ${ doc . ref . path } is not in the correct state to be backfilled`
0 commit comments