From 1cb89bbc1ef458b11c631962b4ad6beea5eaf2c8 Mon Sep 17 00:00:00 2001 From: joel Date: Fri, 22 Nov 2024 10:08:46 -0800 Subject: [PATCH] fix: fixes EGG-380 --- .../sync-posts-to-egghead-lessons.ts | 55 +++++++++++++++++ apps/egghead/src/inngest/inngest.config.ts | 2 + apps/egghead/src/inngest/inngest.server.ts | 5 ++ apps/egghead/src/lib/egghead.ts | 59 ++++++++++++++----- apps/egghead/src/lib/posts-query.ts | 27 ++++++++- 5 files changed, 130 insertions(+), 18 deletions(-) create mode 100644 apps/egghead/src/inngest/functions/sync-posts-to-egghead-lessons.ts diff --git a/apps/egghead/src/inngest/functions/sync-posts-to-egghead-lessons.ts b/apps/egghead/src/inngest/functions/sync-posts-to-egghead-lessons.ts new file mode 100644 index 000000000..09d2906f6 --- /dev/null +++ b/apps/egghead/src/inngest/functions/sync-posts-to-egghead-lessons.ts @@ -0,0 +1,55 @@ +import { eggheadPgQuery } from '@/db/eggheadPostgres' +import { + getAllPostIds, + getPost, + writePostUpdateToDatabase, +} from '@/lib/posts-query' +import { z } from 'zod' + +import { inngest } from '../inngest.server' + +export const SYNC_POSTS_TO_EGGHEAD_LESSONS_EVENT = + 'posts/sync-to-egghead-lessons' + +export type SyncPostsToEggheadLessonsEvent = { + name: typeof SYNC_POSTS_TO_EGGHEAD_LESSONS_EVENT + data: {} +} + +export const syncPostsToEggheadLessons = inngest.createFunction( + { + id: 'sync-posts-to-egghead-lessons', + name: 'Sync ALL lesson posts to egghead lessons', + }, + { event: SYNC_POSTS_TO_EGGHEAD_LESSONS_EVENT }, + async ({ event, step }) => { + const postIds = await step.run('Get post ids', async () => { + return await getAllPostIds() + }) + + // Process each post ID sequentially to avoid race conditions + for (const postId of postIds) { + const post = await step.run(`load-post-${postId}`, async () => { + return await getPost(postId) + }) + + if (!post) { + continue + } + + await step.run(`sync-post-${postId}`, async () => { + const eggheadLessonId = post.fields.eggheadLessonId + + if (eggheadLessonId) { + await writePostUpdateToDatabase({ + postUpdate: post, + action: 'save', + updatedById: 'egghead', + }) + } + }) + } + + return { success: true } + }, +) diff --git a/apps/egghead/src/inngest/inngest.config.ts b/apps/egghead/src/inngest/inngest.config.ts index 0042de0b3..137ded867 100644 --- a/apps/egghead/src/inngest/inngest.config.ts +++ b/apps/egghead/src/inngest/inngest.config.ts @@ -8,6 +8,7 @@ import { notifySlack } from './functions/notify-slack-for-post' import { syncLessonToSanity } from './functions/sanity/sync-lesson-to-sanity' import { syncVideoResourceToSanity } from './functions/sanity/sync-video-resource-to-sanity' import { syncPostToEgghead } from './functions/sync-post-to-egghead' +import { syncPostsToEggheadLessons } from './functions/sync-posts-to-egghead-lessons' import { syncVideoResourceData } from './functions/video-resource-created' export const inngestConfig = { @@ -23,5 +24,6 @@ export const inngestConfig = { syncVideoResourceToSanity, notifySlack, syncVideoResourceData, + syncPostsToEggheadLessons, ], } diff --git a/apps/egghead/src/inngest/inngest.server.ts b/apps/egghead/src/inngest/inngest.server.ts index 226b0c232..bb6621694 100644 --- a/apps/egghead/src/inngest/inngest.server.ts +++ b/apps/egghead/src/inngest/inngest.server.ts @@ -33,6 +33,10 @@ import { POST_UPDATED_EVENT, PostUpdated, } from './functions/sync-post-to-egghead' +import { + SYNC_POSTS_TO_EGGHEAD_LESSONS_EVENT, + SyncPostsToEggheadLessonsEvent, +} from './functions/sync-posts-to-egghead-lessons' // Create a client to send and receive events export type Events = { @@ -43,6 +47,7 @@ export type Events = { [TIPS_UPDATED_EVENT]: TipsUpdated [EGGHEAD_LESSON_CREATED_EVENT]: EggheadLessonCreated [POST_CREATED_EVENT]: PostCreated + [SYNC_POSTS_TO_EGGHEAD_LESSONS_EVENT]: SyncPostsToEggheadLessonsEvent } const callbackBase = diff --git a/apps/egghead/src/lib/egghead.ts b/apps/egghead/src/lib/egghead.ts index fba8e47d0..35747af9b 100644 --- a/apps/egghead/src/lib/egghead.ts +++ b/apps/egghead/src/lib/egghead.ts @@ -80,21 +80,32 @@ export async function createEggheadLesson(input: { hlsUrl?: string }) { const { title, slug, guid, instructorId, hlsUrl = null } = input + const eggheadLessonResult = await eggheadPgQuery( `INSERT INTO lessons (title, instructor_id, slug, resource_type, state, - created_at, updated_at, visibility_state, guid, current_video_hls_url) - VALUES ($1, $2, $3, $4, $5,NOW(), NOW(), $6, $7) + created_at, updated_at, visibility_state, guid${hlsUrl ? ', current_video_hls_url' : ''}) + VALUES ($1, $2, $3, $4, $5, NOW(), NOW(), $6, $7${hlsUrl ? ', $8' : ''}) RETURNING id`, - [ - title, - instructorId, - slug, - EGGHEAD_LESSON_TYPE, - EGGHEAD_INITIAL_LESSON_STATE, - 'hidden', - guid, - hlsUrl, - ], + hlsUrl + ? [ + title, + instructorId, + slug, + EGGHEAD_LESSON_TYPE, + EGGHEAD_INITIAL_LESSON_STATE, + 'hidden', + guid, + hlsUrl, + ] + : [ + title, + instructorId, + slug, + EGGHEAD_LESSON_TYPE, + EGGHEAD_INITIAL_LESSON_STATE, + 'hidden', + guid, + ], ) const eggheadLessonId = eggheadLessonResult.rows[0].id @@ -111,6 +122,9 @@ export async function createEggheadLesson(input: { export async function updateEggheadLesson(input: { eggheadLessonId: number + title: string + slug: string + guid: string state: string visibilityState: string duration: number @@ -122,6 +136,9 @@ export async function updateEggheadLesson(input: { visibilityState, duration, hlsUrl = null, + title, + slug, + guid, } = input await eggheadPgQuery( `UPDATE lessons SET @@ -129,9 +146,21 @@ export async function updateEggheadLesson(input: { duration = $2, updated_at = NOW(), visibility_state = $3, - current_video_hls_url = $4 - WHERE id = $5`, - [state, Math.floor(duration), visibilityState, hlsUrl, eggheadLessonId], + current_video_hls_url = $4, + title = $5, + slug = $6, + guid = $7 + WHERE id = $8`, + [ + state, + Math.floor(duration), + visibilityState, + hlsUrl, + title, + slug, + guid, + eggheadLessonId, + ], ) } diff --git a/apps/egghead/src/lib/posts-query.ts b/apps/egghead/src/lib/posts-query.ts index b6718edd1..1dc9fed67 100644 --- a/apps/egghead/src/lib/posts-query.ts +++ b/apps/egghead/src/lib/posts-query.ts @@ -413,7 +413,7 @@ export async function writeNewPostToDatabase(input: { } export async function writePostUpdateToDatabase(input: { - currentPost: Post + currentPost?: Post postUpdate: PostUpdate action: PostAction updatedById: string @@ -435,9 +435,11 @@ export async function writePostUpdateToDatabase(input: { let postSlug = updatePostSlug(currentPost, postUpdate.fields.title) + const postGuid = currentPost?.fields.slug.split('~')[1] || guid() + if (postUpdate.fields.title !== currentPost.fields.title) { - const splitSlug = currentPost?.fields.slug.split('~') || ['', guid()] - postSlug = `${slugify(postUpdate.fields.title ?? '')}~${splitSlug[1] || guid()}` + const splitSlug = currentPost?.fields.slug.split('~') || ['', postGuid] + postSlug = `${slugify(postUpdate.fields.title ?? '')}~${postGuid}` } const lessonState = determineEggheadLessonState( @@ -464,8 +466,13 @@ export async function writePostUpdateToDatabase(input: { ? await courseBuilderAdapter.getVideoResource(videoResourceId) : null + // probably update sanity here + if (currentPost.fields.eggheadLessonId) { await updateEggheadLesson({ + title: postUpdate.fields.title, + slug: postSlug, // probably bypassing friendly id here, does it matter? + guid: postGuid, eggheadLessonId: currentPost.fields.eggheadLessonId, state: lessonState, visibilityState: lessonVisibilityState, @@ -716,3 +723,17 @@ export async function removeSection( .delete(contentResourceResource) .where(eq(contentResourceResource.resourceId, sectionId)) } + +export async function getAllPostIds() { + return await db.query.contentResource + .findMany({ + where: and( + eq(contentResource.type, 'post'), + sql`JSON_EXTRACT(${contentResource.fields}, '$.postType') = 'lesson'`, + ), + columns: { + id: true, + }, + }) + .then((posts) => posts.map((post) => post.id)) +}