Skip to content

Commit f95dd57

Browse files
committed
combine get_conn and cursor statements
1 parent e75f3ea commit f95dd57

File tree

1 file changed

+86
-94
lines changed
  • services/question-service/app

1 file changed

+86
-94
lines changed

services/question-service/app/crud.py

Lines changed: 86 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,30 @@ def list_difficulties_and_topics() -> Dict[str, List[str]]:
1212
- difficulties (list[str]): List of all available difficulty levels
1313
- topics (list[str]): List of all available topics
1414
"""
15-
with get_conn() as conn:
16-
with conn.cursor() as cur:
17-
cur.execute("SELECT * FROM difficulties")
18-
difficulties = [row[0] for row in cur.fetchall()]
15+
with get_conn() as conn, conn.cursor() as cur:
16+
cur.execute("SELECT * FROM difficulties")
17+
difficulties = [row[0] for row in cur.fetchall()]
1918

20-
cur.execute("SELECT * FROM topics")
21-
topics = [row[0] for row in cur.fetchall()]
19+
cur.execute("SELECT * FROM topics")
20+
topics = [row[0] for row in cur.fetchall()]
2221

23-
return {"difficulties": difficulties, "topics": topics}
22+
return {"difficulties": difficulties, "topics": topics}
2423

2524
def add_difficulty(difficulty: str):
26-
with get_conn() as conn:
27-
with conn.cursor() as cur:
28-
cur.execute("INSERT INTO difficulties (name) VALUES (%s) ON CONFLICT DO NOTHING", (difficulty,))
25+
with get_conn() as conn, conn.cursor() as cur:
26+
cur.execute("INSERT INTO difficulties (name) VALUES (%s) ON CONFLICT DO NOTHING", (difficulty,))
2927

3028
def delete_difficulty(difficulty: str):
31-
with get_conn() as conn:
32-
with conn.cursor() as cur:
33-
cur.execute("DELETE FROM difficulties WHERE level = %s", (difficulty,))
29+
with get_conn() as conn, conn.cursor() as cur:
30+
cur.execute("DELETE FROM difficulties WHERE level = %s", (difficulty,))
3431

3532
def add_topic(topic: str):
36-
with get_conn() as conn:
37-
with conn.cursor() as cur:
38-
cur.execute("INSERT INTO topics (name) VALUES (%s) ON CONFLICT DO NOTHING", (topic,))
33+
with get_conn() as conn, conn.cursor() as cur:
34+
cur.execute("INSERT INTO topics (name) VALUES (%s) ON CONFLICT DO NOTHING", (topic,))
3935

4036
def delete_topic(topic: str):
41-
with get_conn() as conn:
42-
with conn.cursor() as cur:
43-
cur.execute("DELETE FROM topics WHERE name = %s", (topic,))
37+
with get_conn() as conn, conn.cursor() as cur:
38+
cur.execute("DELETE FROM topics WHERE name = %s", (topic,))
4439

4540
def create_question(
4641
name: str,
@@ -121,34 +116,33 @@ def get_question(qid: str):
121116
Note:
122117
Images are returned as raw bytes data retrieved directly from S3.
123118
"""
124-
with get_conn() as conn:
125-
with conn.cursor() as cur:
126-
# Fetch the main question data
127-
cur.execute(
128-
"SELECT name, description, difficulty, topic FROM questions WHERE id = %s",
129-
(qid,),
130-
)
131-
question_data = cur.fetchone()
119+
with get_conn() as conn, conn.cursor() as cur:
120+
# Fetch the main question data
121+
cur.execute(
122+
"SELECT name, description, difficulty, topic FROM questions WHERE id = %s",
123+
(qid,),
124+
)
125+
question_data = cur.fetchone()
132126

133-
if not question_data:
134-
raise QuestionNotFoundException(qid)
127+
if not question_data:
128+
raise QuestionNotFoundException(qid)
135129

136-
# Fetch associated image keys
137-
cur.execute(
138-
"SELECT s3_key FROM question_images WHERE question_id = %s",
139-
(qid,)
140-
)
141-
image_keys = [row[0] for row in cur.fetchall()]
142-
image_data = get_from_s3(image_keys)
130+
# Fetch associated image keys
131+
cur.execute(
132+
"SELECT s3_key FROM question_images WHERE question_id = %s",
133+
(qid,)
134+
)
135+
image_keys = [row[0] for row in cur.fetchall()]
136+
image_data = get_from_s3(image_keys)
143137

144-
return {
145-
"id": qid,
146-
"name": question_data[0],
147-
"description": question_data[1],
148-
"difficulty": question_data[2],
149-
"topic": question_data[3],
150-
"images": image_data, # Raw bytes
151-
}
138+
return {
139+
"id": qid,
140+
"name": question_data[0],
141+
"description": question_data[1],
142+
"difficulty": question_data[2],
143+
"topic": question_data[3],
144+
"images": image_data, # Raw bytes
145+
}
152146

153147

154148
def get_random_question_by_difficulty_and_topic(difficulty: str, topic: str):
@@ -170,39 +164,38 @@ def get_random_question_by_difficulty_and_topic(difficulty: str, topic: str):
170164
Images are returned as raw bytes data retrieved directly from S3.
171165
Uses database RANDOM() function for selection.
172166
"""
173-
with get_conn() as conn:
174-
with conn.cursor() as cur:
175-
cur.execute(
176-
"""
177-
SELECT id, name, description, difficulty, topic
178-
FROM questions
179-
WHERE difficulty = %s AND topic = %s
180-
ORDER BY RANDOM()
181-
LIMIT 1
182-
""",
183-
(difficulty, topic),
184-
)
185-
row = cur.fetchone()
186-
if not row:
187-
raise QuestionNotFoundException(topic=topic, difficulty=difficulty)
167+
with get_conn() as conn, conn.cursor() as cur:
168+
cur.execute(
169+
"""
170+
SELECT id, name, description, difficulty, topic
171+
FROM questions
172+
WHERE difficulty = %s AND topic = %s
173+
ORDER BY RANDOM()
174+
LIMIT 1
175+
""",
176+
(difficulty, topic),
177+
)
178+
row = cur.fetchone()
179+
if not row:
180+
raise QuestionNotFoundException(topic=topic, difficulty=difficulty)
188181

189-
qid = row[0]
190-
# Fetch associated image keys
191-
cur.execute(
192-
"SELECT s3_key FROM question_images WHERE question_id = %s",
193-
(qid,),
194-
)
195-
image_keys = [r[0] for r in cur.fetchall()]
196-
image_data = get_from_s3(image_keys)
182+
qid = row[0]
183+
# Fetch associated image keys
184+
cur.execute(
185+
"SELECT s3_key FROM question_images WHERE question_id = %s",
186+
(qid,),
187+
)
188+
image_keys = [r[0] for r in cur.fetchall()]
189+
image_data = get_from_s3(image_keys)
197190

198-
return {
199-
"id": qid,
200-
"name": row[1],
201-
"description": row[2],
202-
"difficulty": row[3],
203-
"topic": row[4],
204-
"images": image_data, # Raw bytes
205-
}
191+
return {
192+
"id": qid,
193+
"name": row[1],
194+
"description": row[2],
195+
"difficulty": row[3],
196+
"topic": row[4],
197+
"images": image_data, # Raw bytes
198+
}
206199

207200

208201
def override_question(
@@ -287,25 +280,24 @@ def delete_question(qid: str):
287280
This function is atomic: if deleting images from S3 fails,
288281
the database transaction is rolled back to maintain consistency.
289282
"""
290-
with get_conn() as conn:
291-
with conn.cursor() as cur:
292-
# Fetch associated image keys
293-
cur.execute(
294-
"SELECT s3_key FROM question_images WHERE question_id = %s",
295-
(qid,)
296-
)
297-
image_keys = [row[0] for row in cur.fetchall()]
283+
with get_conn() as conn, conn.cursor() as cur:
284+
# Fetch associated image keys
285+
cur.execute(
286+
"SELECT s3_key FROM question_images WHERE question_id = %s",
287+
(qid,)
288+
)
289+
image_keys = [row[0] for row in cur.fetchall()]
298290

299-
# Delete the question and verify it existed
300-
cur.execute("DELETE FROM questions WHERE id = %s RETURNING id", (qid,))
301-
deleted = cur.fetchone()
302-
if not deleted:
303-
raise QuestionNotFoundException(qid)
291+
# Delete the question and verify it existed
292+
cur.execute("DELETE FROM questions WHERE id = %s RETURNING id", (qid,))
293+
deleted = cur.fetchone()
294+
if not deleted:
295+
raise QuestionNotFoundException(qid)
304296

305-
# Delete images from S3; rollback DB if this fails
306-
try:
307-
delete_from_s3(image_keys)
308-
except Exception:
309-
conn.rollback()
310-
raise
297+
# Delete images from S3; rollback DB if this fails
298+
try:
299+
delete_from_s3(image_keys)
300+
except Exception:
301+
conn.rollback()
302+
raise
311303

0 commit comments

Comments
 (0)