From e3e80a5fd0f17e73a2d6fc16bfb25e33ab765526 Mon Sep 17 00:00:00 2001 From: Austin Chen Date: Thu, 8 Sep 2022 20:21:29 -0700 Subject: [PATCH] Change user info using bulkWriter --- functions/src/change-user-info.ts | 74 ++++++++++++++++--------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/functions/src/change-user-info.ts b/functions/src/change-user-info.ts index aa041856..ca66f1ba 100644 --- a/functions/src/change-user-info.ts +++ b/functions/src/change-user-info.ts @@ -37,6 +37,45 @@ export const changeUser = async ( avatarUrl?: string } ) => { + // Update contracts, comments, and answers outside of a transaction to avoid contention. + // Using bulkWriter to supports >500 writes at a time + const contractsRef = firestore + .collection('contracts') + .where('creatorId', '==', user.id) + + const contracts = await contractsRef.get() + + const contractUpdate: Partial = removeUndefinedProps({ + creatorName: update.name, + creatorUsername: update.username, + creatorAvatarUrl: update.avatarUrl, + }) + + const commentSnap = await firestore + .collectionGroup('comments') + .where('userUsername', '==', user.username) + .get() + + const commentUpdate: Partial = removeUndefinedProps({ + userName: update.name, + userUsername: update.username, + userAvatarUrl: update.avatarUrl, + }) + + const answerSnap = await firestore + .collectionGroup('answers') + .where('username', '==', user.username) + .get() + const answerUpdate: Partial = removeUndefinedProps(update) + + const bulkWriter = firestore.bulkWriter() + commentSnap.docs.forEach((d) => bulkWriter.update(d.ref, commentUpdate)) + answerSnap.docs.forEach((d) => bulkWriter.update(d.ref, answerUpdate)) + contracts.docs.forEach((d) => bulkWriter.update(d.ref, contractUpdate)) + await bulkWriter.flush() + console.log('Done writing!') + + // Update the username inside a transaction return await firestore.runTransaction(async (transaction) => { if (update.username) { update.username = cleanUsername(update.username) @@ -58,42 +97,7 @@ export const changeUser = async ( const userRef = firestore.collection('users').doc(user.id) const userUpdate: Partial = removeUndefinedProps(update) - - const contractsRef = firestore - .collection('contracts') - .where('creatorId', '==', user.id) - - const contracts = await transaction.get(contractsRef) - - const contractUpdate: Partial = removeUndefinedProps({ - creatorName: update.name, - creatorUsername: update.username, - creatorAvatarUrl: update.avatarUrl, - }) - - const commentSnap = await transaction.get( - firestore - .collectionGroup('comments') - .where('userUsername', '==', user.username) - ) - - const commentUpdate: Partial = removeUndefinedProps({ - userName: update.name, - userUsername: update.username, - userAvatarUrl: update.avatarUrl, - }) - - const answerSnap = await transaction.get( - firestore - .collectionGroup('answers') - .where('username', '==', user.username) - ) - const answerUpdate: Partial = removeUndefinedProps(update) - transaction.update(userRef, userUpdate) - commentSnap.docs.forEach((d) => transaction.update(d.ref, commentUpdate)) - answerSnap.docs.forEach((d) => transaction.update(d.ref, answerUpdate)) - contracts.docs.forEach((d) => transaction.update(d.ref, contractUpdate)) }) }