Skip to content

Commit 5911a99

Browse files
authored
Merge pull request #1209 from AtCoder-NoviSteps/#1202
🐛 Fixed bug that caused updates to fail due to unique constraint violations (#1202)
2 parents 0e7f925 + 7657f7f commit 5911a99

File tree

3 files changed

+48
-40
lines changed

3 files changed

+48
-40
lines changed

src/lib/actions/update_task_result.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const updateTaskResult = async (
2626

2727
await crud.updateTaskResult(taskId, submissionStatus, userId);
2828
} catch (error) {
29-
console.log('Failed to update task result: ', error);
29+
console.error('Failed to update task result: ', error);
3030
return fail(BAD_REQUEST);
3131
}
3232
};

src/lib/services/answers.ts

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,5 @@
1-
//import { answers } from '$lib/server/sample_data';
2-
//import taskAnswerSchema from '$lib/server/taskanswer';
3-
4-
//server/databaseのインポートでは保存がうまくいかず。
5-
//import { PrismaClient } from '@prisma/client';
6-
//import {defineTaskAnswerFactory } from '../../../prisma/.fabbrica';
7-
// import { PrismaClient } from '@prisma/client';
8-
// prisma.taskAnswer.createが実行できれば、defineTaskAnswerFactoryをインポートしなくて済むはずです。
9-
// また、initializeは、内部メソッドを直接インポートすることで対処できそうです。
10-
111
import { initialize } from '@quramy/prisma-fabbrica/lib/internal';
12-
//import { initialize, defineTaskAnswerFactory } from '../../__generated__/fabbrica';
132

14-
//import { default as prisma } from '$lib/server/database';
15-
//const prisma = new PrismaClient();
163
import { default as prisma } from '$lib/server/database';
174
import type { TaskAnswer } from '@prisma/client';
185
import { sha256 } from '$lib/utils/hash';
@@ -64,7 +51,6 @@ export async function getAnswer(task_id: string, user_id: string) {
6451
return answers_from_db[0];
6552
}
6653

67-
// TODO: createAnswer()
6854
export async function createAnswer(task_id: string, user_id: string, status_id: string) {
6955
const id = await sha256(task_id + user_id);
7056
const taskanswerInput: TaskAnswer = {
@@ -76,13 +62,42 @@ export async function createAnswer(task_id: string, user_id: string, status_id:
7662
updated_at: new Date(),
7763
};
7864

79-
//const taskAnswerFactory = defineTaskAnswerFactory();
8065
const taskAnswer = await prisma.taskAnswer.create({
8166
data: taskanswerInput,
8267
});
8368

8469
return taskAnswer;
8570
}
8671

72+
export async function upsertAnswer(taskId: string, userId: string, statusId: string) {
73+
try {
74+
const id = await sha256(taskId + userId);
75+
const newAnswer = {
76+
id: id,
77+
task_id: taskId,
78+
user_id: userId,
79+
status_id: statusId,
80+
created_at: new Date(),
81+
updated_at: new Date(),
82+
};
83+
84+
await prisma.taskAnswer.upsert({
85+
where: {
86+
task_id_user_id: { task_id: taskId, user_id: userId },
87+
},
88+
update: {
89+
status_id: statusId,
90+
},
91+
create: newAnswer, // await createAnswer(taskId, userId, statusId)とすると、一意制約違反(P2002)が発生するため
92+
});
93+
} catch (error) {
94+
console.error(
95+
`Failed to update answer with taskId ${taskId}, userId ${userId}, statusId: ${statusId}:`,
96+
error,
97+
);
98+
throw error;
99+
}
100+
}
101+
87102
// TODO: updateAnswer()
88103
// TODO: deleteAnswer()

src/lib/services/task_results.ts

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { error } from '@sveltejs/kit';
2+
3+
import { default as db } from '$lib/server/database';
24
import { getTasks, getTask } from '$lib/services/tasks';
3-
import * as answer_crud from './answers';
4-
import type { TaskResult, TaskResults, Tasks } from '$lib/types/task';
5+
import * as answer_crud from '$lib/services/answers';
6+
7+
import type { TaskAnswer } from '$lib/types/answer';
58
import type { Task } from '$lib/types/task';
9+
import type { TaskResult, TaskResults, Tasks } from '$lib/types/task';
610
import type { WorkBookTaskBase, WorkBookTasksBase } from '$lib/types/workbook';
11+
712
import { NOT_FOUND } from '$lib/constants/http-response-status-codes';
8-
import { default as db } from '$lib/server/database';
913
import { getSubmissionStatusMapWithId, getSubmissionStatusMapWithName } from './submission_status';
10-
import type { TaskAnswer } from '../types/answer';
1114

1215
// DBから取得した問題一覧とログインしているユーザの回答を紐付けしたデータ保持
1316
const statusById = await getSubmissionStatusMapWithId();
@@ -170,29 +173,19 @@ export async function getTaskResult(slug: string, userId: string) {
170173
return taskResult;
171174
}
172175

173-
export async function updateTaskResult(slug: string, submissionStatus: string, userId: string) {
174-
const taskResult: TaskResult | null = await getTaskResult(slug, userId);
175-
176-
if (taskResult) {
177-
const status_id = statusByName.get(submissionStatus).id;
176+
export async function updateTaskResult(taskId: string, submissionStatus: string, userId: string) {
177+
const taskResult: TaskResult | null = await getTaskResult(taskId, userId);
178178

179-
const registeredTaskAnswer = await db.taskAnswer.findMany({
180-
where: { task_id: slug, user_id: userId },
181-
});
179+
if (!taskResult) {
180+
console.error(`Failed to get task result for taskId ${taskId} and userId ${userId}`);
181+
return;
182+
}
182183

183-
if (registeredTaskAnswer.length == 0) {
184-
await answer_crud.createAnswer(slug, userId, status_id);
185-
}
184+
const statusId = statusByName.get(submissionStatus).id;
186185

187-
await db.taskAnswer.update({
188-
where: {
189-
task_id_user_id: { task_id: slug, user_id: userId },
190-
},
191-
data: {
192-
status_id: status_id,
193-
},
194-
});
195-
}
186+
await db.$transaction(async () => {
187+
await answer_crud.upsertAnswer(taskId, userId, statusId);
188+
});
196189
}
197190

198191
export async function getTasksWithTagIds(

0 commit comments

Comments
 (0)