From 4894d7fcedca4584948d0a1c82638ef03e3fbe81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Camblor?= Date: Fri, 30 Aug 2024 19:27:10 +0200 Subject: [PATCH] #74 introduced firestore migration in order to introduce speakers in existing events --- ...uceEventSpeakersAndFixTalkUndefinedTags.ts | 39 +++++++++++++++++++ .../firestore/services/talk-utils.ts | 13 +++++-- .../functions/http/migrateFirestoreSchema.ts | 1 + 3 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 cloud/functions/src/functions/firestore/migrations/022-introduceEventSpeakersAndFixTalkUndefinedTags.ts diff --git a/cloud/functions/src/functions/firestore/migrations/022-introduceEventSpeakersAndFixTalkUndefinedTags.ts b/cloud/functions/src/functions/firestore/migrations/022-introduceEventSpeakersAndFixTalkUndefinedTags.ts new file mode 100644 index 00000000..cfe07a76 --- /dev/null +++ b/cloud/functions/src/functions/firestore/migrations/022-introduceEventSpeakersAndFixTalkUndefinedTags.ts @@ -0,0 +1,39 @@ +import {getAllEventsDocs} from "../services/event-utils"; +import {db} from "../../../firebase"; +import {getEventTalks} from "../services/talk-utils"; +import {detailedTalksToSpeakersLineup} from "../../../models/Event"; + + +export async function introduceEventSpeakersAndFixTalkUndefinedTags(): Promise<"OK"|"Error"> { + const eventDocs = await getAllEventsDocs({includePrivateSpaces: true}) + await Promise.all([ + ...eventDocs.map(async eventDoc => { + try { + const eventTalks = await getEventTalks(eventDoc.ref, eventDoc.id); + + // Migrating event talks with empty tags in it + const migratedEventTalks = await Promise.all(eventTalks.map(async eventTalk => { + if(!eventTalk.tags) { + await db.doc(`${eventDoc.ref.path}/talks/${eventTalk.id}`).update("tags", []) + return { + ...eventTalk, + tags: [] + }; + } else { + return eventTalk; + } + })) + + const lineupSpeakers = detailedTalksToSpeakersLineup(migratedEventTalks); + + const eventSpeakersDoc = db.doc(`${eventDoc.ref.path}/speakers-allInOne/self`) + await eventSpeakersDoc.set({ lineupSpeakers }); + console.log(`Event speakers created for event id ${eventDoc.id}`) + } catch (err) { + console.error(`Error during Event speaker creation for ${eventDoc.id}: ${err}`) + } + }), + ]) + + return "OK" +} diff --git a/cloud/functions/src/functions/firestore/services/talk-utils.ts b/cloud/functions/src/functions/firestore/services/talk-utils.ts index 32a29809..251bc859 100644 --- a/cloud/functions/src/functions/firestore/services/talk-utils.ts +++ b/cloud/functions/src/functions/firestore/services/talk-utils.ts @@ -8,10 +8,12 @@ import {logPerf} from "../../http/utils"; import {getTimeslottedTalks} from "./schedule-utils"; import {firestore} from "firebase-admin"; import QuerySnapshot = firestore.QuerySnapshot; -import {Talk} from "../../../../../../shared/daily-schedule.firestore"; +import {DetailedTalk, Talk} from "../../../../../../shared/daily-schedule.firestore"; import stringSimilarity from "string-similarity-js"; import {EventRecordingConfig} from "../../../../../../shared/conference-descriptor.firestore"; import {resolvedEventFirestorePath} from "../../../../../../shared/utilities/event-utils"; +import DocumentReference = firestore.DocumentReference; +import {match, P} from "ts-pattern"; type PerTalkPublicUserIdFeedbackRating = { @@ -77,9 +79,14 @@ export async function getTalksDetailsWithRatings(maybeSpaceToken: string|undefin }) } -export async function getEventTalks(maybeSpaceToken: string|undefined, eventId: string) { +export async function getEventTalks(maybeSpaceToken: DocumentReference|string|undefined, eventId: string) { return logPerf(`getEventTalks(${maybeSpaceToken}, ${eventId})`, async () => { - const talkSnapshots = await db.collection(`${resolvedEventFirestorePath(eventId, maybeSpaceToken)}/talks`).get() as QuerySnapshot + const eventPath = match(maybeSpaceToken) + .with(P.nullish, () => resolvedEventFirestorePath(eventId, undefined)) + .with(P.string, (spaceToken) => resolvedEventFirestorePath(eventId, spaceToken)) + .otherwise(ref => ref.path) + + const talkSnapshots = await db.collection(`${eventPath}/talks`).get() as QuerySnapshot return talkSnapshots.docs.map(snap => snap.data()); }) diff --git a/cloud/functions/src/functions/http/migrateFirestoreSchema.ts b/cloud/functions/src/functions/http/migrateFirestoreSchema.ts index f51a396b..a4c9471e 100644 --- a/cloud/functions/src/functions/http/migrateFirestoreSchema.ts +++ b/cloud/functions/src/functions/http/migrateFirestoreSchema.ts @@ -30,6 +30,7 @@ const MIGRATIONS: Migration[] = [ { name: "introduceFormattingsFeature", exec: async () => (await import("../firestore/migrations/019-introduceFormattingsFeature")).introduceFormattingsFeature() }, { name: "cleaningUnusedFirestoreDocs", exec: async () => (await import("../firestore/migrations/020-cleaningUnusedFirestoreDocs")).cleaningUnusedFirestoreDocs() }, { name: "introduceEventVisibility", exec: async () => (await import("../firestore/migrations/021-introduceEventVisibility")).introduceEventVisibility() }, + { name: "introduceEventSpeakersAndFixTalkUndefinedTags", exec: async () => (await import("../firestore/migrations/022-introduceEventSpeakersAndFixTalkUndefinedTags")).introduceEventSpeakersAndFixTalkUndefinedTags() }, ]; export type MigrationResult = "OK"|"Error";