1
1
import { Container } from "@azure/cosmos" ;
2
2
import { fetchQuestions } from "./repoQuestions" ;
3
- import { getContainer } from "./cosmos-client" ;
3
+ import { getQuestionsContainer } from "./cosmos-client" ;
4
4
5
5
export const QuestionsDataSource = ( container : Container ) => {
6
6
return {
@@ -68,101 +68,137 @@ export const RepoQuestionsDataSource = (container: any) => {
68
68
} ;
69
69
} ;
70
70
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
+
71
77
export const CombinedQuestionsDataSource = ( ) => {
72
78
return {
73
79
async getQuestion ( id : string , link : string ) {
74
80
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
83
101
const questions = await fetchQuestions ( link ) ;
84
102
if ( questions ) {
85
103
const question = questions . find ( ( q : any ) => q . id === id ) ;
86
104
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
+
88
111
try {
89
- await examContainer . items . upsert ( question ) ;
112
+ await questionsContainer . items . upsert ( questionWithExamId ) ;
90
113
} catch ( err ) {
91
114
console . warn ( "Failed to upload question to Cosmos DB:" , err ) ;
92
115
}
93
116
return question ;
94
117
}
95
118
}
96
119
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 ;
106
121
} catch ( err ) {
107
122
throw new Error ( "Error fetching question: " + err ) ;
108
123
}
109
124
} ,
110
125
111
126
async getQuestions ( link : string ) {
112
127
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
121
145
const questions = await fetchQuestions ( link ) ;
122
146
if ( questions ) {
123
- // Upload all questions to exam-specific container
147
+ // Upload all questions to database (only if they don't exist)
124
148
try {
125
149
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 ) ;
127
155
}
128
156
} catch ( err ) {
129
157
console . warn ( "Failed to upload questions to Cosmos DB:" , err ) ;
130
158
}
131
159
return { count : questions . length } ;
132
160
}
133
161
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 } ;
142
163
} catch ( err ) {
143
164
throw new Error ( "Error fetching questions: " + err ) ;
144
165
}
145
166
} ,
146
167
147
168
async getRandomQuestions ( range : number , link : string ) {
148
169
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
157
189
const questions = await fetchQuestions ( link ) ;
158
190
if ( questions ) {
159
191
const shuffled = [ ...questions ] . sort ( ( ) => 0.5 - Math . random ( ) ) ;
160
192
const selected = shuffled . slice ( 0 , range ) ;
161
193
162
- // Upload selected questions to exam-specific container
194
+ // Upload selected questions to database (only if they don't exist)
163
195
try {
164
196
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 ) ;
166
202
}
167
203
} catch ( err ) {
168
204
console . warn ( "Failed to upload questions to Cosmos DB:" , err ) ;
@@ -171,15 +207,7 @@ export const CombinedQuestionsDataSource = () => {
171
207
return selected ;
172
208
}
173
209
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 [ ] ;
183
211
} catch ( err ) {
184
212
throw new Error ( "Error fetching random questions: " + err ) ;
185
213
}
0 commit comments