@@ -4,7 +4,7 @@ import type {
44} from "@dev-team-fall-25/server/convex/http" ;
55import { eq } from "drizzle-orm" ;
66import { Hono } from "hono" ;
7- import type z from "zod" ;
7+ import * as z from "zod/mini " ;
88import getDB from "./drizzle" ;
99import { errorLogs , jobs } from "./drizzle/schema" ;
1010import { ConvexApi } from "./lib/convex" ;
@@ -20,40 +20,102 @@ app.get("/", async (c) => {
2020 return c . json ( { status : "ok" } ) ;
2121} ) ;
2222
23+ const ZCacheData = z . object ( {
24+ isMajorsEnabled : z . transform ( ( val ) => val === "true" ) ,
25+ isCoursesEnabled : z . transform ( ( val ) => val === "true" ) ,
26+ } ) ;
27+
2328export default {
2429 fetch : app . fetch ,
2530
2631 async scheduled ( _event : ScheduledEvent , env : CloudflareBindings ) {
27- // NOTE: the worker will not execute anything for now until the flag for toggle scrapers are set up
28- return ;
29- // biome-ignore lint/correctness/noUnreachable: WIP
3032 const db = getDB ( env ) ;
33+ const convex = new ConvexApi ( {
34+ baseUrl : env . CONVEX_SITE_URL ,
35+ apiKey : env . CONVEX_API_KEY ,
36+ } ) ;
3137
32- // FIXME: need to handle when programsUr or coursesUrl is empty array
33- const programsUrl = new URL ( "/programs" , env . SCRAPING_BASE_URL ) . toString ( ) ;
34- const coursesUrl = new URL ( "/courses" , env . SCRAPING_BASE_URL ) . toString ( ) ;
35-
36- const [ [ programsJob ] , [ coursesJob ] ] = await Promise . all ( [
37- db
38- . insert ( jobs )
39- . values ( {
40- url : programsUrl ,
41- jobType : "discover-programs" ,
42- } )
43- . returning ( ) ,
44- db
45- . insert ( jobs )
46- . values ( {
47- url : coursesUrl ,
48- jobType : "discover-courses" ,
49- } )
50- . returning ( ) ,
51- ] ) ;
38+ const cache = caches . default ;
39+ const cacheKey = `${ env . CONVEX_SITE_URL } /app-configs` ;
40+
41+ let isMajorsEnabled = false ;
42+ let isCoursesEnabled = false ;
43+
44+ // Check to see if app configs are cached
45+ const cached = await cache . match ( cacheKey ) ;
46+ if ( cached ) {
47+ const { data, success } = ZCacheData . safeParse ( await cached . json ( ) ) ;
48+
49+ if ( ! success ) {
50+ throw new JobError ( "Failed to parse cache data" , "validation" ) ;
51+ }
52+
53+ isMajorsEnabled = data . isMajorsEnabled ;
54+ isCoursesEnabled = data . isCoursesEnabled ;
55+ } else {
56+ const [ isScrapingMajors , isScrapingCourses ] = await Promise . all ( [
57+ convex . getAppConfig ( { key : "is_scraping_majors" } ) ,
58+ convex . getAppConfig ( { key : "is_scraping_courses" } ) ,
59+ ] ) ;
60+
61+ isMajorsEnabled = isScrapingMajors === "true" ;
62+ isCoursesEnabled = isScrapingCourses === "true" ;
63+
64+ await cache . put (
65+ cacheKey ,
66+ new Response (
67+ JSON . stringify ( {
68+ isScrapingMajors,
69+ isScrapingCourses,
70+ } ) ,
71+ {
72+ headers : { "Cache-Control" : "max-age=3600" } ,
73+ } ,
74+ ) ,
75+ ) ;
76+ }
77+
78+ const jobsToCreate : Array < {
79+ url : string ;
80+ jobType : "discover-programs" | "discover-courses" ;
81+ } > = [ ] ;
82+ const flagsToDisable : string [ ] = [ ] ;
83+
84+ // add major discovery job to the queue
85+ if ( isMajorsEnabled ) {
86+ const programsUrl = new URL (
87+ "/programs" ,
88+ env . SCRAPING_BASE_URL ,
89+ ) . toString ( ) ;
90+ jobsToCreate . push ( { url : programsUrl , jobType : "discover-programs" } ) ;
91+ flagsToDisable . push ( "is_scraping_majors" ) ;
92+ }
93+
94+ // add course discovery job to the queue
95+ if ( isCoursesEnabled ) {
96+ const coursesUrl = new URL ( "/courses" , env . SCRAPING_BASE_URL ) . toString ( ) ;
97+ jobsToCreate . push ( { url : coursesUrl , jobType : "discover-courses" } ) ;
98+ flagsToDisable . push ( "is_scraping_courses" ) ;
99+ }
100+
101+ if ( jobsToCreate . length === 0 ) {
102+ console . log ( "No scraping jobs enabled, skipping" ) ;
103+ return ;
104+ }
105+
106+ const createdJobs = await db . insert ( jobs ) . values ( jobsToCreate ) . returning ( ) ;
52107
53108 await Promise . all ( [
54- env . SCRAPING_QUEUE . send ( { jobId : programsJob . id } ) ,
55- env . SCRAPING_QUEUE . send ( { jobId : coursesJob . id } ) ,
109+ ...createdJobs . map ( ( job ) => env . SCRAPING_QUEUE . send ( { jobId : job . id } ) ) ,
110+ ...flagsToDisable . map ( ( flag ) =>
111+ convex . setAppConfig ( { key : flag , value : "false" } ) ,
112+ ) ,
113+ cache . delete ( cacheKey ) ,
56114 ] ) ;
115+
116+ console . log (
117+ `Created ${ createdJobs . length } jobs [${ createdJobs . map ( ( j ) => j . jobType ) . join ( ", " ) } ], disabled flags: ${ flagsToDisable . join ( ", " ) } ` ,
118+ ) ;
57119 } ,
58120
59121 async queue (
0 commit comments