1- import { and , eq } from 'drizzle-orm' ;
1+ import { and , eq , inArray } from 'drizzle-orm' ;
22
33import { db } from '@/db' ;
4- import { quizAnswers , quizQuestions } from '@/db/schema/quiz' ;
4+ import {
5+ quizAnswers ,
6+ quizAnswerTranslations ,
7+ quizQuestionContent ,
8+ quizQuestions } from '@/db/schema/quiz' ;
59import { getRedisClient } from '@/lib/redis' ;
10+ import type { QuizQuestionWithAnswers } from '@/types/quiz' ;
611
712interface QuizAnswersCache {
813 quizId : string ;
914 answers : Record < string , string > ;
1015 cachedAt : number ;
1116}
1217
13- function getCacheKey ( quizId : string ) : string {
18+ interface QuizQuestionsCache {
19+ quizId : string ;
20+ locale : string ;
21+ questions : QuizQuestionWithAnswers [ ] ;
22+ cachedAt : number ;
23+ }
24+
25+ function getQuestionsCacheKey ( quizId : string , locale : string ) : string {
26+ return `quiz:questions:${ quizId } :${ locale } ` ;
27+ }
28+
29+
30+ function getAnswersCacheKey ( quizId : string ) : string {
1431 return `quiz:answers:${ quizId } ` ;
1532}
1633
@@ -23,7 +40,7 @@ export async function getOrCreateQuizAnswersCache(
2340 return true ;
2441 }
2542
26- const key = getCacheKey ( quizId ) ;
43+ const key = getAnswersCacheKey ( quizId ) ;
2744
2845 const existing = await redis . get < QuizAnswersCache > ( key ) ;
2946 if ( existing ) {
@@ -67,7 +84,7 @@ export async function getCorrectAnswer(
6784 const redis = getRedisClient ( ) ;
6885
6986 if ( redis ) {
70- const key = getCacheKey ( quizId ) ;
87+ const key = getAnswersCacheKey ( quizId ) ;
7188 const cache = await redis . get < QuizAnswersCache > ( key ) ;
7289 if ( cache ) {
7390 return cache . answers [ questionId ] ?? null ;
@@ -89,3 +106,93 @@ export async function getCorrectAnswer(
89106
90107 return result [ 0 ] ?. answerId ?? null ;
91108}
109+
110+ export async function getOrCreateQuestionsCache (
111+ quizId : string ,
112+ locale : string
113+ ) : Promise < QuizQuestionWithAnswers [ ] | null > {
114+ const redis = getRedisClient ( ) ;
115+ if ( ! redis ) {
116+ return null ;
117+ }
118+
119+ const key = getQuestionsCacheKey ( quizId , locale ) ;
120+
121+ const existing = await redis . get < QuizQuestionsCache > ( key ) ;
122+ if ( existing ) {
123+ return existing . questions ;
124+ }
125+
126+ const questionsData = await db
127+ . select ( {
128+ id : quizQuestions . id ,
129+ displayOrder : quizQuestions . displayOrder ,
130+ difficulty : quizQuestions . difficulty ,
131+ questionText : quizQuestionContent . questionText ,
132+ explanation : quizQuestionContent . explanation ,
133+ } )
134+ . from ( quizQuestions )
135+ . leftJoin (
136+ quizQuestionContent ,
137+ and (
138+ eq ( quizQuestionContent . quizQuestionId , quizQuestions . id ) ,
139+ eq ( quizQuestionContent . locale , locale )
140+ )
141+ )
142+ . where ( eq ( quizQuestions . quizId , quizId ) )
143+ . orderBy ( quizQuestions . displayOrder ) ;
144+
145+ if ( questionsData . length === 0 ) {
146+ return [ ] ;
147+ }
148+
149+ const questionIds = questionsData . map ( q => q . id ) ;
150+
151+ const allAnswers = await db
152+ . select ( {
153+ id : quizAnswers . id ,
154+ questionId : quizAnswers . quizQuestionId ,
155+ displayOrder : quizAnswers . displayOrder ,
156+ isCorrect : quizAnswers . isCorrect ,
157+ answerText : quizAnswerTranslations . answerText ,
158+ } )
159+ . from ( quizAnswers )
160+ . leftJoin (
161+ quizAnswerTranslations ,
162+ and (
163+ eq ( quizAnswerTranslations . quizAnswerId , quizAnswers . id ) ,
164+ eq ( quizAnswerTranslations . locale , locale )
165+ )
166+ )
167+ . where ( inArray ( quizAnswers . quizQuestionId , questionIds ) )
168+ . orderBy ( quizAnswers . displayOrder ) ;
169+
170+ const answersByQuestion = new Map < string , typeof allAnswers > ( ) ;
171+ for ( const answer of allAnswers ) {
172+ const arr = answersByQuestion . get ( answer . questionId ) || [ ] ;
173+ arr . push ( answer ) ;
174+ answersByQuestion . set ( answer . questionId , arr ) ;
175+ }
176+
177+
178+ const questions : QuizQuestionWithAnswers [ ] = questionsData . map ( q => ( {
179+ ...q ,
180+ answers : ( answersByQuestion . get ( q . id ) || [ ] ) . map ( a => ( {
181+ id : a . id ,
182+ displayOrder : a . displayOrder ,
183+ isCorrect : a . isCorrect ,
184+ answerText : a . answerText ,
185+ } ) ) ,
186+ } ) ) ;
187+
188+ const cacheData : QuizQuestionsCache = {
189+ quizId,
190+ locale,
191+ questions,
192+ cachedAt : Date . now ( ) ,
193+ } ;
194+
195+ await redis . set ( key , cacheData ) ;
196+
197+ return questions ;
198+ }
0 commit comments