11import { Container } from "@azure/cosmos" ;
22import { fetchQuestions } from "./repoQuestions" ;
3- import { getContainer } from "./cosmos-client" ;
3+ import { getQuestionsContainer } from "./cosmos-client" ;
44
55export const QuestionsDataSource = ( container : Container ) => {
66 return {
@@ -68,101 +68,137 @@ export const RepoQuestionsDataSource = (container: any) => {
6868 } ;
6969} ;
7070
71+ // Helper function to extract exam ID from URL
72+ const extractExamId = ( link : string ) : string => {
73+ const segments = link . split ( "/" ) ;
74+ return segments [ segments . length - 3 ] . replace ( / - / g, "_" ) . toLowerCase ( ) ;
75+ } ;
76+
7177export const CombinedQuestionsDataSource = ( ) => {
7278 return {
7379 async getQuestion ( id : string , link : string ) {
7480 try {
75- // Extract exam name from URL and create a safe container name
76- const segments = link . split ( "/" ) ;
77- const examName = segments [ segments . length - 3 ]
78- . replace ( / - / g, "_" )
79- . toLowerCase ( ) ;
80- const examContainer = await getContainer ( examName ) ;
81-
82- // Try GitHub first
81+ const examId = extractExamId ( link ) ;
82+ const questionsContainer = await getQuestionsContainer ( ) ;
83+
84+ // Try Cosmos DB first (most efficient)
85+ const querySpec = {
86+ query : "SELECT * FROM c WHERE c.id = @id AND c.examId = @examId" ,
87+ parameters : [
88+ { name : "@id" , value : id } ,
89+ { name : "@examId" , value : examId } ,
90+ ] ,
91+ } ;
92+ const { resources : items } = await questionsContainer . items
93+ . query ( querySpec )
94+ . fetchAll ( ) ;
95+
96+ if ( items . length > 0 ) {
97+ return items [ 0 ] ;
98+ }
99+
100+ // Fallback to GitHub if not found in database
83101 const questions = await fetchQuestions ( link ) ;
84102 if ( questions ) {
85103 const question = questions . find ( ( q : any ) => q . id === id ) ;
86104 if ( question ) {
87- // Upload to exam-specific container
105+ // Add examId to the question document and upload to database
106+ const questionWithExamId = {
107+ ...question ,
108+ examId : examId ,
109+ } ;
110+
88111 try {
89- await examContainer . items . upsert ( question ) ;
112+ await questionsContainer . items . upsert ( questionWithExamId ) ;
90113 } catch ( err ) {
91114 console . warn ( "Failed to upload question to Cosmos DB:" , err ) ;
92115 }
93116 return question ;
94117 }
95118 }
96119
97- // Fallback to Cosmos DB
98- const querySpec = {
99- query : "SELECT * FROM c WHERE c.id = @id" ,
100- parameters : [ { name : "@id" , value : id } ] ,
101- } ;
102- const { resources : items } = await examContainer . items
103- . query ( querySpec )
104- . fetchAll ( ) ;
105- return items [ 0 ] ;
120+ return null ;
106121 } catch ( err ) {
107122 throw new Error ( "Error fetching question: " + err ) ;
108123 }
109124 } ,
110125
111126 async getQuestions ( link : string ) {
112127 try {
113- // Extract exam name from URL and create a safe container name
114- const segments = link . split ( "/" ) ;
115- const examName = segments [ segments . length - 3 ]
116- . replace ( / - / g, "_" )
117- . toLowerCase ( ) ;
118- const examContainer = await getContainer ( examName ) ;
119-
120- // Try GitHub first
128+ const examId = extractExamId ( link ) ;
129+ const questionsContainer = await getQuestionsContainer ( ) ;
130+
131+ // Try Cosmos DB first
132+ const querySpec = {
133+ query : "SELECT VALUE COUNT(c.id) FROM c WHERE c.examId = @examId" ,
134+ parameters : [ { name : "@examId" , value : examId } ] ,
135+ } ;
136+ const { resources : items } = await questionsContainer . items
137+ . query ( querySpec )
138+ . fetchAll ( ) ;
139+
140+ if ( items [ 0 ] > 0 ) {
141+ return { count : items [ 0 ] } ;
142+ }
143+
144+ // Fallback to GitHub if no questions found in database
121145 const questions = await fetchQuestions ( link ) ;
122146 if ( questions ) {
123- // Upload all questions to exam-specific container
147+ // Upload all questions to database (only if they don't exist)
124148 try {
125149 for ( const question of questions ) {
126- await examContainer . items . upsert ( question ) ;
150+ const questionWithExamId = {
151+ ...question ,
152+ examId : examId ,
153+ } ;
154+ await questionsContainer . items . upsert ( questionWithExamId ) ;
127155 }
128156 } catch ( err ) {
129157 console . warn ( "Failed to upload questions to Cosmos DB:" , err ) ;
130158 }
131159 return { count : questions . length } ;
132160 }
133161
134- // Fallback to Cosmos DB
135- const querySpec = {
136- query : "SELECT VALUE COUNT(c.id) FROM c" ,
137- } ;
138- const { resources : items } = await examContainer . items
139- . query ( querySpec )
140- . fetchAll ( ) ;
141- return { count : items [ 0 ] } ;
162+ return { count : 0 } ;
142163 } catch ( err ) {
143164 throw new Error ( "Error fetching questions: " + err ) ;
144165 }
145166 } ,
146167
147168 async getRandomQuestions ( range : number , link : string ) {
148169 try {
149- // Extract exam name from URL and create a safe container name
150- const segments = link . split ( "/" ) ;
151- const examName = segments [ segments . length - 3 ]
152- . replace ( / - / g, "_" )
153- . toLowerCase ( ) ;
154- const examContainer = await getContainer ( examName ) ;
155-
156- // Try GitHub first
170+ const examId = extractExamId ( link ) ;
171+ const questionsContainer = await getQuestionsContainer ( ) ;
172+
173+ // Try Cosmos DB first
174+ const querySpec = {
175+ query : "SELECT * FROM c WHERE c.examId = @examId" ,
176+ parameters : [ { name : "@examId" , value : examId } ] ,
177+ } ;
178+ const { resources : items } = await questionsContainer . items
179+ . query ( querySpec )
180+ . fetchAll ( ) ;
181+
182+ if ( items . length > 0 ) {
183+ // Questions exist in database, return random selection
184+ const shuffled = [ ...items ] . sort ( ( ) => 0.5 - Math . random ( ) ) ;
185+ return shuffled . slice ( 0 , range ) ;
186+ }
187+
188+ // Fallback to GitHub if no questions found in database
157189 const questions = await fetchQuestions ( link ) ;
158190 if ( questions ) {
159191 const shuffled = [ ...questions ] . sort ( ( ) => 0.5 - Math . random ( ) ) ;
160192 const selected = shuffled . slice ( 0 , range ) ;
161193
162- // Upload selected questions to exam-specific container
194+ // Upload selected questions to database (only if they don't exist)
163195 try {
164196 for ( const question of selected ) {
165- await examContainer . items . upsert ( question ) ;
197+ const questionWithExamId = {
198+ ...question ,
199+ examId : examId ,
200+ } ;
201+ await questionsContainer . items . upsert ( questionWithExamId ) ;
166202 }
167203 } catch ( err ) {
168204 console . warn ( "Failed to upload questions to Cosmos DB:" , err ) ;
@@ -171,15 +207,7 @@ export const CombinedQuestionsDataSource = () => {
171207 return selected ;
172208 }
173209
174- // Fallback to Cosmos DB
175- const querySpec = {
176- query : "SELECT * FROM c" ,
177- } ;
178- const { resources : items } = await examContainer . items
179- . query ( querySpec )
180- . fetchAll ( ) ;
181- const shuffled = [ ...items ] . sort ( ( ) => 0.5 - Math . random ( ) ) ;
182- return shuffled . slice ( 0 , range ) ;
210+ return [ ] ;
183211 } catch ( err ) {
184212 throw new Error ( "Error fetching random questions: " + err ) ;
185213 }
0 commit comments