Skip to content

Commit

Permalink
chore: tighten up sync (#330)
Browse files Browse the repository at this point in the history
  • Loading branch information
joelhooks authored Nov 22, 2024
1 parent 1cb89bb commit 9e8a5a2
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 38 deletions.
70 changes: 42 additions & 28 deletions apps/egghead/src/lib/egghead.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,32 +81,41 @@ export async function createEggheadLesson(input: {
}) {
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${hlsUrl ? ', current_video_hls_url' : ''})
VALUES ($1, $2, $3, $4, $5, NOW(), NOW(), $6, $7${hlsUrl ? ', $8' : ''})
RETURNING id`,
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 columns = [
'title',
'instructor_id',
'slug',
'resource_type',
'state',
'created_at',
'updated_at',
'visibility_state',
'guid',
...(hlsUrl ? ['current_video_hls_url'] : []),
]

const values = [
title,
instructorId,
slug,
EGGHEAD_LESSON_TYPE,
EGGHEAD_INITIAL_LESSON_STATE,
new Date(), // created_at
new Date(), // updated_at
'hidden',
guid,
...(hlsUrl ? [hlsUrl] : []),
]

const placeholders = columns.map((_, index) => `$${index + 1}`).join(', ')

const query = `
INSERT INTO lessons (${columns.join(', ')})
VALUES (${placeholders})
RETURNING id
`

const eggheadLessonResult = await eggheadPgQuery(query, values)

const eggheadLessonId = eggheadLessonResult.rows[0].id

Expand All @@ -129,6 +138,7 @@ export async function updateEggheadLesson(input: {
visibilityState: string
duration: number
hlsUrl?: string
body?: string
}) {
const {
eggheadLessonId,
Expand All @@ -139,6 +149,7 @@ export async function updateEggheadLesson(input: {
title,
slug,
guid,
body = '',
} = input
await eggheadPgQuery(
`UPDATE lessons SET
Expand All @@ -149,8 +160,9 @@ export async function updateEggheadLesson(input: {
current_video_hls_url = $4,
title = $5,
slug = $6,
guid = $7
WHERE id = $8`,
guid = $7,
summary = $8
WHERE id = $9`,
[
state,
Math.floor(duration),
Expand All @@ -159,6 +171,7 @@ export async function updateEggheadLesson(input: {
title,
slug,
guid,
body,
eggheadLessonId,
],
)
Expand Down Expand Up @@ -233,6 +246,7 @@ export const eggheadLessonSchema = z.object({
summary: z.string().nullish(),
topic_list: z.array(z.string()),
free_forever: z.boolean(),
is_pro: z.boolean(),
body: z.string().nullish(),
state: z.string(),
instructor: z.object({
Expand Down
23 changes: 19 additions & 4 deletions apps/egghead/src/lib/posts-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
contentResourceTag as contentResourceTagTable,
contentResourceVersion as contentResourceVersionTable,
contributionTypes,
users,
} from '@/db/schema'
import {
generateContentHash,
Expand All @@ -28,7 +27,6 @@ import { subject } from '@casl/ability'
import slugify from '@sindresorhus/slugify'
import { and, asc, desc, eq, like, or, sql } from 'drizzle-orm'
import readingTime from 'reading-time'
import Typesense from 'typesense'
import { z } from 'zod'

import 'server-only'
Expand All @@ -51,6 +49,10 @@ import {
updateEggheadLesson,
writeLegacyTaggingsToEgghead,
} from './egghead'
import {
replaceSanityLessonResources,
updateSanityLesson,
} from './sanity-content-query'
import { EggheadTag, EggheadTagSchema } from './tags'
import { upsertPostToTypeSense } from './typesense'

Expand Down Expand Up @@ -385,6 +387,14 @@ export async function writeNewPostToDatabase(input: {

const post = await getPost(newPostId)

if (post && post.fields.eggheadLessonId) {
await updateSanityLesson(post.fields.eggheadLessonId, post)
await replaceSanityLessonResources({
eggheadLessonId: post.fields.eggheadLessonId,
videoResourceId: videoResourceId,
})
}

await createNewPostVersion(post)

if (post) {
Expand Down Expand Up @@ -466,13 +476,12 @@ 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,
body: postUpdate.fields.body ?? '',
eggheadLessonId: currentPost.fields.eggheadLessonId,
state: lessonState,
visibilityState: lessonVisibilityState,
Expand All @@ -498,6 +507,12 @@ export async function writePostUpdateToDatabase(input: {
throw new Error(`Post with id ${currentPost.id} not found.`)
}

await updateSanityLesson(currentPost.fields.eggheadLessonId, updatedPost)
await replaceSanityLessonResources({
eggheadLessonId: currentPost.fields.eggheadLessonId,
videoResourceId: videoResourceId,
})

const newContentHash = generateContentHash(updatedPost)
const currentContentHash = currentPost.currentVersionId?.split('~')[1]

Expand Down
1 change: 1 addition & 0 deletions apps/egghead/src/lib/posts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const PostUpdateSchema = z.object({
title: z.string().min(2).max(90),
postType: PostTypeSchema.optional().default('lesson'),
body: z.string().optional().nullable(),
description: z.string().optional().nullable(),
visibility: PostVisibilitySchema.optional().default('public'),
state: PostStateSchema.optional().default('draft'),
}),
Expand Down
118 changes: 112 additions & 6 deletions apps/egghead/src/lib/sanity-content-query.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
'use server'

import type { EggheadLesson } from '@/lib/egghead'
import { courseBuilderAdapter, db } from '@/db'
import { contentResource } from '@/db/schema'
import { getEggheadLesson, type EggheadLesson } from '@/lib/egghead'
import {
keyGenerator,
sanityCollaboratorDocumentSchema,
sanityCollaboratorReferenceObjectSchema,
sanityLessonDocumentSchema,
sanitySoftwareLibraryDocumentSchema,
sanityVersionedSoftwareLibraryObjectSchema,
sanityVideoResourceDocumentSchema,
} from '@/lib/sanity-content'
import type {
Expand All @@ -15,9 +19,12 @@ import type {
SanityVersionedSoftwareLibraryObject,
} from '@/lib/sanity-content'
import { sanityWriteClient } from '@/server/sanity-write-client'
import { eq, sql } from 'drizzle-orm'

import type { VideoResource } from '@coursebuilder/core/schemas'

import { Post } from './posts'

export async function createSanityVideoResource(videoResource: VideoResource) {
const { muxPlaybackId, muxAssetId, transcript, srt, id } = videoResource

Expand Down Expand Up @@ -49,11 +56,49 @@ export async function createSanityVideoResource(videoResource: VideoResource) {
return sanityVideoResourceDocument
}

export async function replaceSanityLessonResources({
eggheadLessonId,
videoResourceId,
}: {
eggheadLessonId: number | null | undefined
videoResourceId: string | null | undefined
}) {
if (!eggheadLessonId || !videoResourceId) return

const videoResource =
await courseBuilderAdapter.getVideoResource(videoResourceId)

if (!videoResource) {
throw new Error(`Video resource with id ${videoResourceId} not found.`)
}

const sanityLessonDocument =
await getSanityLessonForEggheadLessonId(eggheadLessonId)

const sanityVideoResourceDocument =
await createSanityVideoResource(videoResource)

return await sanityWriteClient
.patch(sanityLessonDocument._id)
.set({
resources: [
{
_key: keyGenerator(),
_type: 'reference',
_ref: sanityVideoResourceDocument._id,
},
],
})
.commit()
}

export async function patchSanityLessonWithVideoResourceReference(
eggheadLessonId: number,
eggheadLessonId: number | null | undefined,
videoResourceDocumentId: string,
) {
const sanityLessonDocument = await getSanityLesson(eggheadLessonId)
if (!eggheadLessonId) return
const sanityLessonDocument =
await getSanityLessonForEggheadLessonId(eggheadLessonId)

if (!sanityLessonDocument) return

Expand All @@ -72,7 +117,7 @@ export async function patchSanityLessonWithVideoResourceReference(
.commit()
}

export async function getSanityLesson(
export async function getSanityLessonForEggheadLessonId(
eggheadLessonId: number | null | undefined,
) {
if (!eggheadLessonId) return
Expand All @@ -82,22 +127,83 @@ export async function getSanityLesson(
)
}

export async function updateSanityLesson(
eggheadLessonId: number | null | undefined,
lesson?: Post | null,
) {
if (!eggheadLessonId || !lesson) return

const sanityLessonDocument =
await getSanityLessonForEggheadLessonId(eggheadLessonId)
const eggheadLesson = await getEggheadLesson(eggheadLessonId)

if (!sanityLessonDocument || !eggheadLesson) return

const softwareLibraries = await Promise.all(
eggheadLesson.topic_list.map(async (library: string) => {
return sanityVersionedSoftwareLibraryObjectSchema.parse(
await getSanitySoftwareLibrary(library),
)
}),
)

const collaborator = sanityCollaboratorReferenceObjectSchema.parse(
await getSanityCollaborator(eggheadLesson.instructor.id),
)

await sanityWriteClient
.patch(sanityLessonDocument._id)
.set({
description: lesson.fields.body,
status: eggheadLesson.state,
accessLevel: eggheadLesson.is_pro
? 'pro'
: eggheadLesson.free_forever
? 'free'
: 'pro',
title: lesson.fields.title,
slug: {
_type: 'slug',
current: lesson.fields.slug,
},
collaborators: [collaborator],
softwareLibraries,
})
.commit()
}

export async function createSanityLesson(
eggheadLesson: EggheadLesson,
collaborator: SanityCollaboratorReferenceObject,
softwareLibraries: SanityVersionedSoftwareLibraryObject[],
) {
const post = await db.query.contentResource.findFirst({
where: eq(
sql`JSON_EXTRACT (${contentResource.fields}, "$.eggheadLessonId")`,
eggheadLesson.id,
),
})

if (!post) {
throw new Error(`Post with id ${eggheadLesson.id} not found.`)
}

const lesson = sanityLessonDocumentSchema.parse({
_id: `lesson-${eggheadLesson.id}`,
_type: 'lesson',
title: eggheadLesson.title,
slug: {
_type: 'slug',
current: eggheadLesson.slug,
},
description: eggheadLesson.body,
description: post?.fields?.body,
railsLessonId: eggheadLesson.id,
status: eggheadLesson.state,
accessLevel: eggheadLesson.free_forever ? 'free' : 'pro',
accessLevel: eggheadLesson.is_pro
? 'pro'
: eggheadLesson.free_forever
? 'free'
: 'pro',
collaborators: [collaborator],
softwareLibraries,
})
Expand Down

0 comments on commit 9e8a5a2

Please sign in to comment.