Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/prabhat/frontend' into yitong/d5…
Browse files Browse the repository at this point in the history
…-frontend
  • Loading branch information
yitong241 committed Nov 5, 2024
2 parents f198e74 + 07b5eec commit 979696f
Show file tree
Hide file tree
Showing 18 changed files with 574 additions and 278 deletions.
2 changes: 1 addition & 1 deletion backend/communication-service/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ COPY . .

RUN npx prisma migrate dev --name init

EXPOSE 3004
EXPOSE 3004 9000

CMD ["npm", "run", "start"]
1 change: 1 addition & 0 deletions backend/matching-service/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ yarn.lock
*.swp
*~
dev.db
dev.db-journal
migrations/
1 change: 1 addition & 0 deletions backend/matching-service/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/matching-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"amqplib": "^0.10.4",
"axios": "^1.7.7",
"body-parser": "^1.20.3",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.21.1",
"jwt-decode": "^4.0.0",
Expand Down
71 changes: 38 additions & 33 deletions backend/matching-service/src/matchingService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { io } from "./server";
import { PrismaClient } from "@prisma/client";
import { v4 as uuidv4 } from "uuid";
import { fetchRandomQuestion } from "./util";
import exp from "constants";

const prisma = new PrismaClient();

Expand All @@ -11,7 +12,7 @@ const CONFIRM_DELAY_TIME = 10000;

export async function handleMatchingRequest(
userRequest: any,
socketId: string,
socketId: string
) {
userRequest.socketId = socketId;

Expand All @@ -36,11 +37,11 @@ function sendConfirmDelayedTimeoutMessage(recordId: string) {
recordId: recordId,
type: "confirm_timeout",
},
CONFIRM_DELAY_TIME,
CONFIRM_DELAY_TIME
);
console.log(
"Sent delayed message for confirm timeout for recordId: ",
recordId,
recordId
);
}

Expand All @@ -58,7 +59,7 @@ export async function handleUserRequest(userRequest: any) {
console.log("Duplicate socket detected. New socket will be used.");
io.to(pastSocketId).emit(
"duplicate socket",
"New connection detected for the same user. Please close the current page",
"New connection detected for the same user. Please close the current page"
);

// Update socket ID upon potential reconnection
Expand All @@ -85,9 +86,19 @@ export async function handleUserRequest(userRequest: any) {
if (existingMatch !== null) {
const roomNumber = uuidv4();
const question = await fetchRandomQuestion(difficulty, topic);
console.log(
`Match found for ${userId} with ${existingMatch.userId} on topic ${topic}, difficulty ${difficulty}, roomNumber ${roomNumber}`,
);

if (!question) {
io.to(socketId).emit("question_error", {
message: "No Question found for the selected topic and difficulty",
});
io.to(existingMatch.socketId).emit("question_error", {
message: "No Question found for the selected topic and difficulty",
});
await prisma.matchRecord.delete({
where: { recordId: existingMatch.recordId },
});
return;
}
// Match found, update both records to mark as isPending
await prisma.matchRecord.update({
where: { recordId: existingMatch.recordId },
Expand All @@ -103,26 +114,20 @@ export async function handleUserRequest(userRequest: any) {
matchedUserId: existingMatch.userId,
isPending: true,
roomNumber,
questionId: question.questionId,
questionId: question?.questionId as number,
},
});

console.log(
`Matched ${userId} with ${existingMatch.userId} on topic ${topic}, difficulty ${difficulty}`,
);

console.log("Question matched with", question.questionId);

// Update both clients about the successful match
io.to(socketId).emit("matched", {
matchedWith: existingMatch.userId,
roomNumber,
questionId: question.questionId,
questionId: question?.questionId,
});
io.to(existingMatch.socketId).emit("matched", {
matchedWith: userId,
roomNumber,
questionId: question.questionId,
questionId: question?.questionId,
});

// Add confirm timeout messages
Expand Down Expand Up @@ -164,7 +169,7 @@ export async function handleMatchingConfirm(userRequest: any) {
});
io.to(matchedRecord.socketId).emit(
"other_declined",
"Match not confirmed. Please try again.",
"Match not confirmed. Please try again."
);
}
if (userRecord !== null) {
Expand All @@ -174,7 +179,7 @@ export async function handleMatchingConfirm(userRequest: any) {
});
io.to(userRecord.socketId).emit(
"other_declined",
"Match not confirmed. Please try again.",
"Match not confirmed. Please try again."
);
}
return;
Expand Down Expand Up @@ -206,20 +211,20 @@ export async function handleMatchingConfirm(userRequest: any) {

io.to(userRecord.socketId).emit(
"matching_success",
"Match confirmed. Proceeding to collaboration service.",
"Match confirmed. Proceeding to collaboration service."
);
io.to(matchedRecord.socketId).emit(
"matching_success",
"Match confirmed. Proceeding to collaboration service.",
"Match confirmed. Proceeding to collaboration service."
);
// TODO: add further logic here to proceed to collaboration service
} else {
console.log(
`User ${userId} confirmed match, waiting for other user to confirm`,
`User ${userId} confirmed match, waiting for other user to confirm`
);
io.to(matchedRecord.socketId).emit(
"other_accepted",
"Other user confirmed match. Please confirm.",
"Other user confirmed match. Please confirm."
);
}
}
Expand All @@ -243,11 +248,11 @@ export async function handleMatchingDecline(userRequest: any) {
});
io.to(matchedRecord.socketId).emit(
"other_declined",
"Match not confirmed. Please try again.",
"Match not confirmed. Please try again."
);
io.to(matchedRecord.socketId).emit(
"matching_fail",
"Match not confirmed. Please try again.",
"Match not confirmed. Please try again."
);
}
if (userRecord !== null) {
Expand All @@ -257,11 +262,11 @@ export async function handleMatchingDecline(userRequest: any) {
});
io.to(userRecord.socketId).emit(
"other_declined",
"Match not confirmed. Please try again.",
"Match not confirmed. Please try again."
);
io.to(userRecord.socketId).emit(
"matching_fail",
"Match not confirmed. Please try again.",
"Match not confirmed. Please try again."
);
}

Expand All @@ -277,7 +282,7 @@ export async function handleMatchingDecline(userRequest: any) {
console.log(`User ${userId} declined match`);
io.to(matchedRecord.socketId).emit(
"other_declined",
"Match not confirmed. Please try again.",
"Match not confirmed. Please try again."
);
await prisma.matchRecord.update({
where: { recordId: matchedRecord.recordId },
Expand All @@ -286,11 +291,11 @@ export async function handleMatchingDecline(userRequest: any) {

io.to(userRecord.socketId).emit(
"matching_fail",
"Match not confirmed. Please try again.",
"Match not confirmed. Please try again."
);
io.to(matchedRecord.socketId).emit(
"matching_fail",
"Match not confirmed. Please try again.",
"Match not confirmed. Please try again."
);
}

Expand Down Expand Up @@ -323,16 +328,16 @@ export async function handleConfirmTimeout(recordId: string) {
if (result !== null) {
if (result.isConfirmed === false) {
console.log(
`Timeout: Match not confirmed for recordId ${recordId} with userId ${result.userId}`,
`Timeout: Match not confirmed for recordId ${recordId} with userId ${result.userId}`
);
} else {
console.log(
`Timeout: Match confirmed for recordId ${recordId} with userId ${result.userId} but other user did not confirm`,
`Timeout: Match confirmed for recordId ${recordId} with userId ${result.userId} but other user did not confirm`
);
}
io.to(result.socketId).emit(
"matching_fail",
"Match not confirmed. Please try again.",
"Match not confirmed. Please try again."
);
await prisma.matchRecord.update({
where: { recordId: recordIdInt },
Expand All @@ -351,4 +356,4 @@ export async function handleDisconnected(socketId: string) {
data: { isArchived: true },
});
}
}
}
13 changes: 13 additions & 0 deletions backend/matching-service/src/model/question.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
interface Question {
questionId: Number;
title: string;
description: string;
categories: string[];
complexity: "Easy" | "Medium" | "Hard";
link: string;
testCases: {
input: string;
output: string;
}[];
}
export default Question;
38 changes: 38 additions & 0 deletions backend/matching-service/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,46 @@ import {
handleDisconnected,
} from "./matchingService";

import cors from "cors";
import { PrismaClient } from "@prisma/client";

const app = express();

app.use(express.json());

app.use(
cors({
origin: "*",
})
);

const prisma = new PrismaClient();

app.post("/check", async (req, res) => {
const { userId, roomId } = req.body.data;

const record = await prisma.matchRecord.findFirst({
where: {
roomNumber: roomId,
OR: [
{
userId: userId,
},
{
matchedUserId: userId,
},
],
matched: true,
},
});

if (!record) {
res.status(200).json({ hasAccess: false });
} else {
res.status(200).json({ hasAccess: true });
}
});

const server = createServer(app);
export const io = new Server(server, {
cors: {
Expand Down
12 changes: 10 additions & 2 deletions backend/matching-service/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import axios from "axios";
import { configDotenv } from "dotenv";
import Question from "./model/question";

configDotenv();
const fetchRandomQuestion = async (complexity: string, categories: string) => {
const fetchRandomQuestion = async (
complexity: string,
categories: string
): Promise<Question | null> => {
const response = await axios.post(`${process.env.QUESTION_SERVICE}/random`, {
complexity,
categories,
});
return response.data;
if (response.status !== 200) {
return null;
} else {
return response.data;
}
};

export { fetchRandomQuestion };
20 changes: 16 additions & 4 deletions backend/question-service/src/routes/questionRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,19 @@ router.post("/random", async (req: Request, res: Response) => {
});

if (!question) {
return res.status(404).json({ message: "Question not found" });
const otherQuestion = await Question.find({
categories: { $all: categories },
});

if (!otherQuestion) {
return res
.status(404)
.json({ message: "Question not found with given categories" });
} else {
const randomQuestion =
otherQuestion[Math.floor(Math.random() * otherQuestion.length)];
res.status(200).json(randomQuestion);
}
} else {
const randomQuestion =
question[Math.floor(Math.random() * question.length)];
Expand Down Expand Up @@ -83,7 +95,7 @@ router.put("/:id", async (req: Request, res: Response) => {
const updatedQuestion = await Question.findOneAndUpdate(
{ questionId: id },
{ title, description, categories, complexity },
{ new: true },
{ new: true }
);
if (!updatedQuestion)
return res.status(404).json({ error: "Question not found" });
Expand Down Expand Up @@ -126,7 +138,7 @@ router.post("/test/:id", async (req: Request, res: Response) => {
const tests = plainToInstance(Test, [req.body]);
console.assert(
tests.length === 1,
"tests must be an array of exactly 1 element",
"tests must be an array of exactly 1 element"
);
const test = tests[0];
const errors = await validate(test);
Expand All @@ -139,7 +151,7 @@ router.post("/test/:id", async (req: Request, res: Response) => {

const testCases: TestCase[] = [...question.testCases, ...test.customTests];
const outputPromises = testCases.map((testCase) =>
testCode(test.code, test.lang, testCase, authtoken),
testCode(test.code, test.lang, testCase, authtoken)
);
try {
const outputs = await Promise.all(outputPromises);
Expand Down
3 changes: 2 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ services:
code-execution-rabbitmq:
image: rabbitmq:4.0-management
ports:
- "7000:5672"
- "7004:5672"

code-execution-redis:
image: redis:alpine
Expand Down Expand Up @@ -57,6 +57,7 @@ services:
build: ./backend/communication-service
ports:
- "3004:3004"
- "9000:9000"

matching:
build: ./backend/matching-service
Expand Down
Loading

0 comments on commit 979696f

Please sign in to comment.