-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2397 from concord-consortium/188211348-put-functi…
…on-in-own-file rename and move function to its own file
- Loading branch information
Showing
5 changed files
with
96 additions
and
107 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,4 @@ | ||
import {onDocumentWritten} from "firebase-functions/v2/firestore"; | ||
import * as logger from "firebase-functions/logger"; | ||
import * as admin from "firebase-admin"; | ||
export {onUserDocWritten} from "./on-user-doc-written"; | ||
|
||
admin.initializeApp(); | ||
|
||
export const updateClassDocNetworksOnUserChange = | ||
onDocumentWritten("{root}/{space}/users/{userId}", async (event) => { | ||
const {root, space, userId} = event.params; | ||
|
||
const classesResult = await admin.firestore() | ||
.collection(`${root}/${space}/classes`) | ||
.where("teachers", "array-contains", userId) | ||
.get(); | ||
|
||
// For every class of this teacher update the networks. | ||
// We could do something more efficient in the case where a network was | ||
// added. Or in the case that networks were not changed. | ||
// That can be figured out by looking at the event.data.before and | ||
// event.data.after documents. | ||
// However to keep the code more simple we just always do the scan | ||
// of classes and teachers. This is required when a network is deleted | ||
// because we need to figure out if another teacher in the class still has | ||
// the deleted network. | ||
|
||
// To optimize this we collect all of the teachers we care about | ||
// and make one request for them instead of requesting the teachers for each | ||
// class separately. | ||
|
||
const teacherIdSet = new Set<string>(); | ||
classesResult.forEach((classDoc) => { | ||
const {teachers} = classDoc.data() as {teachers: string[]}; | ||
if (!Array.isArray(teachers)) return; | ||
teachers.forEach((id) => teacherIdSet.add(id)); | ||
}); | ||
|
||
const teacherIds = [...teacherIdSet]; | ||
|
||
const teacherNetworks: Record<string, string[]|undefined> = {}; | ||
|
||
// Need to use batching incase the number of teacherIds is larger than 30 | ||
const batchSize = 30; | ||
for (let i = 0; i < teacherIds.length; i += batchSize) { | ||
const batch = teacherIds.slice(i, i + batchSize); | ||
const teachersResult = await admin.firestore() | ||
.collection(`${root}/${space}/users`) | ||
.where("uid", "in", batch) | ||
.get(); | ||
|
||
teachersResult.forEach((teacherDoc) => { | ||
const teacherData = teacherDoc.data(); | ||
teacherNetworks[teacherData.uid] = teacherData.networks; | ||
}); | ||
} | ||
|
||
const classUpdatePromises: Promise<unknown>[] = []; | ||
classesResult.forEach((classDoc) => { | ||
// Update each class with the networks of each teacher in the class | ||
const {teachers, networks} = classDoc.data() as {teachers: string[], networks: string[] | undefined}; | ||
if (!Array.isArray(teachers)) return; | ||
const classNetworks = new Set<string>(); | ||
teachers.forEach((teacher) => { | ||
const networks = teacherNetworks[teacher]; | ||
if (!networks) return; | ||
networks.forEach((network) => classNetworks.add(network)); | ||
}); | ||
const orderedNetworks = [...classNetworks].sort(); | ||
if (isArrayEqual(networks, orderedNetworks)) return; | ||
|
||
classUpdatePromises.push( | ||
classDoc.ref.update({networks: orderedNetworks}) | ||
); | ||
}); | ||
|
||
await Promise.all(classUpdatePromises); | ||
|
||
logger.info("User updated", event.document); | ||
}); | ||
|
||
function isArrayEqual(array1: string[] | undefined, array2: string[]) { | ||
return array1?.length === array2.length && array1.every((value, index) => value === array2[index]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import {onDocumentWritten} from "firebase-functions/v2/firestore"; | ||
import * as logger from "firebase-functions/logger"; | ||
import * as admin from "firebase-admin"; | ||
import {isArrayEqual} from "./utils"; | ||
|
||
export const onUserDocWritten = | ||
onDocumentWritten("{root}/{space}/users/{userId}", async (event) => { | ||
const {root, space, userId} = event.params; | ||
|
||
const classesResult = await admin.firestore() | ||
.collection(`${root}/${space}/classes`) | ||
.where("teachers", "array-contains", userId) | ||
.get(); | ||
|
||
// For every class of this teacher update the networks. | ||
// We could do something more efficient in the case where a network was | ||
// added. Or in the case that networks were not changed. | ||
// That can be figured out by looking at the event.data.before and | ||
// event.data.after documents. | ||
// However to keep the code more simple we just always do the scan | ||
// of classes and teachers. This is required when a network is deleted | ||
// because we need to figure out if another teacher in the class still has | ||
// the deleted network. | ||
|
||
// To optimize this we collect all of the teachers we care about | ||
// and make one request for them instead of requesting the teachers for each | ||
// class separately. | ||
|
||
const teacherIdSet = new Set<string>(); | ||
classesResult.forEach((classDoc) => { | ||
const {teachers} = classDoc.data() as {teachers: string[]}; | ||
if (!Array.isArray(teachers)) return; | ||
teachers.forEach((id) => teacherIdSet.add(id)); | ||
}); | ||
|
||
const teacherIds = [...teacherIdSet]; | ||
|
||
const teacherNetworks: Record<string, string[]|undefined> = {}; | ||
|
||
// Need to use batching incase the number of teacherIds is larger than 30 | ||
const batchSize = 30; | ||
for (let i = 0; i < teacherIds.length; i += batchSize) { | ||
const batch = teacherIds.slice(i, i + batchSize); | ||
const teachersResult = await admin.firestore() | ||
.collection(`${root}/${space}/users`) | ||
.where("uid", "in", batch) | ||
.get(); | ||
|
||
teachersResult.forEach((teacherDoc) => { | ||
const teacherData = teacherDoc.data(); | ||
teacherNetworks[teacherData.uid] = teacherData.networks; | ||
}); | ||
} | ||
|
||
const classUpdatePromises: Promise<unknown>[] = []; | ||
classesResult.forEach((classDoc) => { | ||
// Update each class with the networks of each teacher in the class | ||
const {teachers, networks} = classDoc.data() as {teachers: string[], networks: string[] | undefined}; | ||
if (!Array.isArray(teachers)) return; | ||
const classNetworks = new Set<string>(); | ||
teachers.forEach((teacher) => { | ||
const networks = teacherNetworks[teacher]; | ||
if (!networks) return; | ||
networks.forEach((network) => classNetworks.add(network)); | ||
}); | ||
const orderedNetworks = [...classNetworks].sort(); | ||
if (isArrayEqual(networks, orderedNetworks)) return; | ||
|
||
classUpdatePromises.push( | ||
classDoc.ref.update({networks: orderedNetworks}) | ||
); | ||
}); | ||
|
||
await Promise.all(classUpdatePromises); | ||
|
||
logger.info("User updated", event.document); | ||
}); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export function isArrayEqual(array1: string[] | undefined, array2: string[]) { | ||
return array1?.length === array2.length && array1.every((value, index) => value === array2[index]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters