Skip to content

Commit

Permalink
Merge pull request #323 from badass-courses/creeland/egg-373-sync-cou…
Browse files Browse the repository at this point in the history
…rse-builder-video-posts-with-egghead-and-sanity

feat: Sync Lessons and Video Resources to Sanity
  • Loading branch information
Creeland authored Nov 18, 2024
2 parents 5425db2 + 2b6b831 commit 826f87a
Show file tree
Hide file tree
Showing 11 changed files with 462 additions and 4 deletions.
15 changes: 15 additions & 0 deletions apps/egghead/src/inngest/events/egghead/lesson-created.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { z } from 'zod'

export const EGGHEAD_LESSON_CREATED_EVENT = 'egghead/lesson-created'

export type EggheadLessonCreated = {
name: typeof EGGHEAD_LESSON_CREATED_EVENT
data: EggheadLessonCreatedEvent
}
export const EggheadLessonCreatedEventSchema = z.object({
id: z.number(),
})

export type EggheadLessonCreatedEvent = z.infer<
typeof EggheadLessonCreatedEventSchema
>
64 changes: 64 additions & 0 deletions apps/egghead/src/inngest/functions/sanity/sync-lesson-to-sanity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { EGGHEAD_LESSON_CREATED_EVENT } from '@/inngest/events/egghead/lesson-created'
import { inngest } from '@/inngest/inngest.server'
import { eggheadLessonSchema, getEggheadLesson } from '@/lib/egghead'
import type { EggheadLesson } from '@/lib/egghead'
import {
sanityCollaboratorDocumentSchema,
sanityCollaboratorReferenceObjectSchema,
sanityVersionedSoftwareLibraryObjectSchema,
} from '@/lib/sanity-content'
import type {
SanityCollaboratorDocument,
SanityCollaboratorReferenceObject,
SanityVersionedSoftwareLibraryObject,
} from '@/lib/sanity-content'
import {
createSanityLesson,
getSanityCollaborator,
getSanitySoftwareLibrary,
} from '@/lib/sanity-content-query'

export const syncLessonToSanity = inngest.createFunction(
{
id: 'sync-lesson-to-sanity',
name: 'Sync Lesson to Sanity',
},
{
event: EGGHEAD_LESSON_CREATED_EVENT,
},
async ({ event, step }) => {
const lesson = (await step.run('Get lesson', async () => {
return eggheadLessonSchema.parse(await getEggheadLesson(event.data.id))
})) as EggheadLesson

const versionedSoftwareLibraryReferences = (await step.run(
'Get an array of versioned software library references',
async () => {
return await Promise.all(
lesson.topic_list.map(async (library: string) => {
return sanityVersionedSoftwareLibraryObjectSchema.parse(
await getSanitySoftwareLibrary(library),
)
}),
)
},
)) as SanityVersionedSoftwareLibraryObject[]

const sanityCollaboratorReferenceObject = (await step.run(
'Get collaborator',
async () => {
return sanityCollaboratorReferenceObjectSchema.parse(
await getSanityCollaborator(lesson.instructor.id),
)
},
)) as SanityCollaboratorReferenceObject

const sanityLesson = await step.run('Create lesson in sanity', async () => {
return await createSanityLesson(
lesson,
sanityCollaboratorReferenceObject,
versionedSoftwareLibraryReferences,
)
})
},
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { courseBuilderAdapter } from '@/db'
import { inngest } from '@/inngest/inngest.server'
import {
createSanityVideoResource,
patchSanityLessonWithVideoResourceReference,
} from '@/lib/sanity-content-query'
import { getResourceOfVideoResource } from '@/lib/video-resource-query'
import { NonRetriableError } from 'inngest'

import { VIDEO_RESOURCE_CREATED_EVENT } from '@coursebuilder/core/inngest/video-processing/events/event-video-resource'
import type { VideoResource } from '@coursebuilder/core/schemas'

export const syncVideoResourceToSanity = inngest.createFunction(
{
id: 'sync-video-resource-to-sanity',
name: 'Sync Video Resource to Sanity',
},
{
event: VIDEO_RESOURCE_CREATED_EVENT,
},
async ({ event, step }) => {
const courseBuilderVideoResource = (await step.run(
'Get video resource',
async () => {
const videoResource = await courseBuilderAdapter.getVideoResource(
event.data.videoResourceId,
)

if (!videoResource) {
throw new NonRetriableError('Video resource not found')
}

return videoResource
},
)) as VideoResource

const sanityVideoResourceDocument = await step.run(
'Create video resource in sanity',
async () => {
return await createSanityVideoResource(courseBuilderVideoResource)
},
)

await step.run(
'Associate video document with lesson via reference',
async () => {
const post = await getResourceOfVideoResource(
courseBuilderVideoResource.id,
)

return patchSanityLessonWithVideoResourceReference(
post?.fields?.eggheadLessonId,
sanityVideoResourceDocument._id,
)
},
)
},
)
4 changes: 4 additions & 0 deletions apps/egghead/src/inngest/inngest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { courseBuilderCoreFunctions } from '@coursebuilder/core/inngest'

import { migrateTipsToPosts } from './functions/migrate-tips-to-posts'
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'

export const inngestConfig = {
Expand All @@ -16,6 +18,8 @@ export const inngestConfig = {
imageResourceCreated,
syncPostToEgghead,
migrateTipsToPosts,
syncLessonToSanity,
syncVideoResourceToSanity,
notifySlack,
],
}
5 changes: 5 additions & 0 deletions apps/egghead/src/inngest/inngest.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import DeepgramProvider from '@coursebuilder/core/providers/deepgram'
import OpenAIProvider from '@coursebuilder/core/providers/openai'
import PartykitProvider from '@coursebuilder/core/providers/partykit'

import {
EGGHEAD_LESSON_CREATED_EVENT,
EggheadLessonCreated,
} from './events/egghead/lesson-created'
import { POST_CREATED_EVENT, PostCreated } from './events/post-created'
import {
TIPS_UPDATED_EVENT,
Expand All @@ -37,6 +41,7 @@ export type Events = {
[USER_CREATED_EVENT]: UserCreated
[POST_UPDATED_EVENT]: PostUpdated
[TIPS_UPDATED_EVENT]: TipsUpdated
[EGGHEAD_LESSON_CREATED_EVENT]: EggheadLessonCreated
[POST_CREATED_EVENT]: PostCreated
}

Expand Down
27 changes: 26 additions & 1 deletion apps/egghead/src/lib/egghead.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { db } from '@/db'
import { eggheadPgQuery } from '@/db/eggheadPostgres'
import { users } from '@/db/schema'
import { EGGHEAD_LESSON_CREATED_EVENT } from '@/inngest/events/egghead/lesson-created'
import { inngest } from '@/inngest/inngest.server'
import { eq } from 'drizzle-orm'
import { z } from 'zod'

import { PostAction, PostState, PostVisibility } from './posts'
import { getPost } from './posts-query'
Expand Down Expand Up @@ -69,7 +72,7 @@ export async function getEggheadLesson(eggheadLessonId: number) {
return lesson
}

export async function crreateEggheadLesson(input: {
export async function createEggheadLesson(input: {
title: string
slug: string
instructorId: string | number
Expand All @@ -92,6 +95,13 @@ export async function crreateEggheadLesson(input: {

const eggheadLessonId = eggheadLessonResult.rows[0].id

await inngest.send({
name: EGGHEAD_LESSON_CREATED_EVENT,
data: {
id: eggheadLessonId,
},
})

return eggheadLessonId
}

Expand Down Expand Up @@ -174,3 +184,18 @@ export async function writeLegacyTaggingsToEgghead(postId: string) {
}
Boolean(query) && (await eggheadPgQuery(query))
}

export const eggheadLessonSchema = z.object({
id: z.number(),
title: z.string(),
slug: z.string(),
summary: z.string().nullish(),
topic_list: z.array(z.string()),
free_forever: z.boolean(),
state: z.string(),
instructor: z.object({
id: z.number(),
}),
})

export type EggheadLesson = z.infer<typeof eggheadLessonSchema>
4 changes: 2 additions & 2 deletions apps/egghead/src/lib/posts-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import { inngest } from '@/inngest/inngest.server'
import { getMuxAsset } from '@coursebuilder/core/lib/mux'

import {
crreateEggheadLesson,
createEggheadLesson,
determineEggheadLessonState,
determineEggheadVisibilityState,
getEggheadUserProfile,
Expand Down Expand Up @@ -316,7 +316,7 @@ export async function writeNewPostToDatabase(input: {
const videoResource =
await courseBuilderAdapter.getVideoResource(videoResourceId)

const eggheadLessonId = await crreateEggheadLesson({
const eggheadLessonId = await createEggheadLesson({
title: title,
slug: `${slugify(title)}~${postGuid}`,
instructorId: eggheadInstructorId,
Expand Down
Loading

0 comments on commit 826f87a

Please sign in to comment.