Skip to content

Commit bcc0d13

Browse files
committed
change create qn history record to be at collab instead of match
1 parent 4e96605 commit bcc0d13

File tree

10 files changed

+120
-60
lines changed

10 files changed

+120
-60
lines changed

backend/collab-service/.env.sample

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ SERVICE_PORT=3003
44
# Origins for cors
55
ORIGINS=http://localhost:5173,http://127.0.0.1:5173
66

7+
QN_HISTORY_SERVICE_URL=http://qn-history-service:3006/api/qnhistories
8+
79
# Redis configuration
810
REDIS_URI=redis://collab-service-redis:6379
911

backend/collab-service/src/handlers/websocketHandler.ts

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Socket } from "socket.io";
22
import { io } from "../server";
33
import redisClient from "../config/redis";
44
import { Doc, applyUpdateV2, encodeStateAsUpdateV2 } from "yjs";
5+
import { qnHistoryService } from "../utils/api";
56

67
enum CollabEvents {
78
// Receive
@@ -55,19 +56,50 @@ export const handleWebsocketCollabEvents = (socket: Socket) => {
5556
}
5657
});
5758

58-
socket.on(CollabEvents.INIT_DOCUMENT, (roomId: string, template: string) => {
59-
const doc = getDocument(roomId);
60-
const isPartnerReady = partnerReadiness.get(roomId);
61-
62-
if (isPartnerReady && doc.getText().length === 0) {
63-
doc.transact(() => {
64-
doc.getText().insert(0, template);
65-
});
66-
io.to(roomId).emit(CollabEvents.DOCUMENT_READY);
67-
} else {
68-
partnerReadiness.set(roomId, true);
59+
socket.on(
60+
CollabEvents.INIT_DOCUMENT,
61+
(
62+
roomId: string,
63+
template: string,
64+
uid1: string,
65+
uid2: string,
66+
language: string,
67+
qnId: string,
68+
qnTitle: string
69+
) => {
70+
const doc = getDocument(roomId);
71+
const isPartnerReady = partnerReadiness.get(roomId);
72+
73+
if (isPartnerReady && doc.getText().length === 0) {
74+
qnHistoryService
75+
.post("/", {
76+
userIds: [uid1, uid2],
77+
questionId: qnId,
78+
title: qnTitle,
79+
submissionStatus: "Attempted",
80+
dateAttempted: new Date(),
81+
timeTaken: 0,
82+
code: template,
83+
language: language,
84+
})
85+
.then((res) => {
86+
console.log("created in collab");
87+
doc.transact(() => {
88+
doc.getText().insert(0, template);
89+
});
90+
io.to(roomId).emit(
91+
CollabEvents.DOCUMENT_READY,
92+
res.data.qnHistory.id
93+
);
94+
})
95+
.catch((err) => {
96+
console.log(err);
97+
});
98+
} else {
99+
partnerReadiness.set(roomId, true);
100+
}
69101
}
70-
});
102+
);
71103

72104
socket.on(
73105
CollabEvents.UPDATE_REQUEST,
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import axios from "axios";
2+
3+
const QN_HISTORY_SERVICE_URL =
4+
process.env.QN_HISTORY_SERVICE_URL ||
5+
"http://qn-history-service:3006/api/qnhistories";
6+
7+
export const qnHistoryService = axios.create({
8+
baseURL: QN_HISTORY_SERVICE_URL,
9+
headers: {
10+
"Content-Type": "application/json",
11+
},
12+
});

backend/matching-service/.env.sample

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ ORIGINS=http://localhost:5173,http://127.0.0.1:5173
66

77
# Other service APIs
88
QUESTION_SERVICE_URL=http://question-service:3000/api/questions
9-
QN_HISTORY_SERVICE_URL=http://qn-history-service:3006/api/qnhistories
109

1110
# RabbitMq configuration
1211
RABBITMQ_DEFAULT_USER=admin

backend/matching-service/src/handlers/websocketHandler.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from "./matchHandler";
1212
import { io } from "../server";
1313
import { v4 as uuidv4 } from "uuid";
14-
import { qnHistoryService, questionService } from "../utils/api";
14+
import { questionService } from "../utils/api";
1515

1616
enum MatchEvents {
1717
// Receive
@@ -129,28 +129,18 @@ export const handleWebsocketMatchEvents = (socket: Socket) => {
129129
return;
130130
}
131131

132-
const { complexity, category, language } = match;
132+
const { complexity, category } = match;
133133
questionService
134134
.get("/random", { params: { complexity, category } })
135135
.then((res) => {
136-
const qnId = res.data.question.id;
137-
qnHistoryService
138-
.post("/", {
139-
userIds: [userId1, userId2],
140-
questionId: qnId,
141-
title: res.data.question.title,
142-
submissionStatus: "Attempted",
143-
dateAttempted: new Date(),
144-
timeTaken: 0,
145-
language: language,
146-
})
147-
.then((res) => {
148-
io.to(matchId).emit(
149-
MatchEvents.MATCH_SUCCESSFUL,
150-
qnId,
151-
res.data.qnHistory.id
152-
);
153-
});
136+
io.to(matchId).emit(
137+
MatchEvents.MATCH_SUCCESSFUL,
138+
res.data.question.id,
139+
res.data.question.title
140+
);
141+
})
142+
.catch((err) => {
143+
console.log(err);
154144
});
155145
}
156146
}

backend/matching-service/src/utils/api.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,9 @@ const QUESTION_SERVICE_URL =
44
process.env.QUESTION_SERVICE_URL ||
55
"http://question-service:3000/api/questions";
66

7-
const QN_HISTORY_SERVICE_URL =
8-
process.env.QN_HISTORY_SERVICE_URL ||
9-
"http://qn-history-service:3006/api/qnhistories";
10-
117
export const questionService = axios.create({
128
baseURL: QUESTION_SERVICE_URL,
139
headers: {
1410
"Content-Type": "application/json",
1511
},
1612
});
17-
18-
export const qnHistoryService = axios.create({
19-
baseURL: QN_HISTORY_SERVICE_URL,
20-
headers: {
21-
"Content-Type": "application/json",
22-
},
23-
});

frontend/src/components/CodeEditor/index.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import { yCollab } from "y-codemirror.next";
1111
import { Text } from "yjs";
1212
import { Awareness } from "y-protocols/awareness";
1313
import { useCollab } from "../../contexts/CollabContext";
14-
import { USE_COLLAB_ERROR_MESSAGE } from "../../utils/constants";
14+
import { USE_COLLAB_ERROR_MESSAGE, USE_MATCH_ERROR_MESSAGE } from "../../utils/constants";
15+
import { useMatch } from "../../contexts/MatchContext";
1516

1617
interface CodeEditorProps {
1718
editorState?: { text: Text; awareness: Awareness };
@@ -40,12 +41,19 @@ const CodeEditor: React.FC<CodeEditorProps> = (props) => {
4041
isReadOnly = false,
4142
} = props;
4243

44+
const match = useMatch();
45+
if (!match) {
46+
throw new Error(USE_MATCH_ERROR_MESSAGE);
47+
}
48+
49+
const { matchCriteria, matchUser, partner, questionId, questionTitle } = match;
50+
4351
const collab = useCollab();
4452
if (!collab) {
4553
throw new Error(USE_COLLAB_ERROR_MESSAGE);
4654
}
4755

48-
const { setCode } = collab;
56+
const { setCode, checkDocReady } = collab;
4957

5058
const [isEditorReady, setIsEditorReady] = useState<boolean>(false);
5159
const [isDocumentLoaded, setIsDocumentLoaded] = useState<boolean>(false);
@@ -66,8 +74,11 @@ const CodeEditor: React.FC<CodeEditorProps> = (props) => {
6674
}
6775

6876
const loadTemplate = async () => {
69-
await initDocument(uid, roomId, template);
70-
setIsDocumentLoaded(true);
77+
if (matchUser && partner && matchCriteria && questionId && questionTitle) {
78+
await initDocument(uid, roomId, template, matchUser.id, partner.id, matchCriteria.language, questionId, questionTitle);
79+
checkDocReady();
80+
setIsDocumentLoaded(true);
81+
}
7182
};
7283
loadTemplate();
7384
// eslint-disable-next-line react-hooks/exhaustive-deps

frontend/src/contexts/CollabContext.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ type CollabContextType = {
4444
isEndSessionModalOpen: boolean;
4545
time: number;
4646
resetCollab: () => void;
47+
checkDocReady: () => void;
4748
};
4849

4950
const CollabContext = createContext<CollabContextType | null>(null);
@@ -65,7 +66,6 @@ const CollabProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
6566
getMatchId,
6667
stopMatch,
6768
questionId,
68-
qnHistoryId,
6969
} = match;
7070

7171
const [time, setTime] = useState<number>(0);
@@ -88,6 +88,8 @@ const CollabProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
8888
const [compilerResult, setCompilerResult] = useState<CompilerResult[]>([]);
8989
const [isEndSessionModalOpen, setIsEndSessionModalOpen] =
9090
useState<boolean>(false);
91+
const [qnHistoryId, setQnHistoryId] = useState<string | null>(null);
92+
let hasSubmitted: boolean = false;
9193

9294
const handleSubmitSessionClick = async () => {
9395
try {
@@ -97,6 +99,7 @@ const CollabProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
9799
code: code.replace(/\t/g, " ".repeat(4)),
98100
language: matchCriteria?.language.toLowerCase(),
99101
});
102+
hasSubmitted = true;
100103
console.log([...res.data.data]);
101104
setCompilerResult([...res.data.data]);
102105

@@ -140,11 +143,8 @@ const CollabProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
140143
const handleConfirmEndSession = async () => {
141144
setIsEndSessionModalOpen(false);
142145

143-
// Get queston history
144-
const data = await qnHistoryClient.get(qnHistoryId as string);
145-
146146
// Only update question history if it has not been submitted before
147-
if (!data.data.qnHistory.code) {
147+
if (!hasSubmitted) {
148148
updateQnHistoryById(
149149
qnHistoryId as string,
150150
{
@@ -172,6 +172,12 @@ const CollabProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
172172
resetCollab();
173173
};
174174

175+
const checkDocReady = () => {
176+
collabSocket.on(CollabEvents.DOCUMENT_READY, (qnHistoryId: string) => {
177+
setQnHistoryId(qnHistoryId);
178+
});
179+
};
180+
175181
const checkPartnerStatus = () => {
176182
collabSocket.on(CollabEvents.PARTNER_LEFT, () => {
177183
toast.error(COLLAB_ENDED_MESSAGE);
@@ -200,6 +206,7 @@ const CollabProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
200206
isEndSessionModalOpen,
201207
time,
202208
resetCollab,
209+
checkDocReady,
203210
}}
204211
>
205212
{children}

frontend/src/contexts/MatchContext.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ type MatchContextType = {
8989
matchPending: boolean;
9090
loading: boolean;
9191
questionId: string | null;
92-
qnHistoryId: string | null;
92+
questionTitle: string | null;
9393
};
9494

9595
const requestTimeoutDuration = 5000;
@@ -115,7 +115,7 @@ const MatchProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
115115
const [matchPending, setMatchPending] = useState<boolean>(false);
116116
const [loading, setLoading] = useState<boolean>(true);
117117
const [questionId, setQuestionId] = useState<string | null>(null);
118-
const [qnHistoryId, setQnHistoryId] = useState<string | null>(null);
118+
const [questionTitle, setQuestionTitle] = useState<string | null>(null);
119119

120120
const navigator = useContext(UNSAFE_NavigationContext).navigator as History;
121121

@@ -277,10 +277,10 @@ const MatchProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
277277
const initMatchedListeners = () => {
278278
matchSocket.on(
279279
MatchEvents.MATCH_SUCCESSFUL,
280-
(qnId: string, qnHistId: string) => {
280+
(qnId: string, title: string) => {
281281
setMatchPending(false);
282282
setQuestionId(qnId);
283-
setQnHistoryId(qnHistId);
283+
setQuestionTitle(title);
284284
appNavigate(MatchPaths.COLLAB);
285285
}
286286
);
@@ -512,7 +512,7 @@ const MatchProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
512512
matchPending,
513513
loading,
514514
questionId,
515-
qnHistoryId,
515+
questionTitle,
516516
}}
517517
>
518518
{children}

frontend/src/utils/collabSocket.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,26 @@ export const join = (
7272
});
7373
};
7474

75-
export const initDocument = (uid: string, roomId: string, template: string) => {
76-
collabSocket.emit(CollabEvents.INIT_DOCUMENT, roomId, template);
75+
export const initDocument = (
76+
uid: string,
77+
roomId: string,
78+
template: string,
79+
uid1: string,
80+
uid2: string,
81+
language: string,
82+
qnId: string,
83+
qnTitle: string
84+
) => {
85+
collabSocket.emit(
86+
CollabEvents.INIT_DOCUMENT,
87+
roomId,
88+
template,
89+
uid1,
90+
uid2,
91+
language,
92+
qnId,
93+
qnTitle
94+
);
7795

7896
return new Promise<void>((resolve) => {
7997
collabSocket.once(CollabEvents.UPDATE, (update) => {

0 commit comments

Comments
 (0)