Skip to content

Commit 1d4c6e8

Browse files
authored
Merge pull request #8 from CODESPACE-CE-PROJECT/CE-008-Compiler
fix: compile c, cpp, java
2 parents 2b107b2 + 2518389 commit 1d4c6e8

File tree

5 files changed

+150
-119
lines changed

5 files changed

+150
-119
lines changed

src/middlewares/auth.middleware.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ export const authorization = async (
1414
res: Response,
1515
next: NextFunction,
1616
) => {
17-
1817
const token: string | undefined = req.headers.authorization?.split(" ")[1];
1918
if (!token) {
2019
return res.status(401).json({ message: "UNAUTHORIZED" });
@@ -36,8 +35,12 @@ export const authorization = async (
3635
}
3736
};
3837

39-
export const authorizationAPIKey = async (req: Request, res: Response, next: NextFunction) => {
40-
const token: string | undefined = req.header('x-api-key')
38+
export const authorizationAPIKey = async (
39+
req: Request,
40+
res: Response,
41+
next: NextFunction,
42+
) => {
43+
const token: string | undefined = req.header("x-api-key");
4144
if (!token) {
4245
return res.status(401).json({ message: "Invalid API Key" });
4346
}
@@ -49,4 +52,4 @@ export const authorizationAPIKey = async (req: Request, res: Response, next: Nex
4952
} catch (error) {
5053
return res.status(401).json({ message: "Invalid API Key" });
5154
}
52-
}
55+
};

src/services/compiler.service.ts

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -56,45 +56,42 @@ export const compilerService = {
5656
try {
5757
const regex = /\w+/;
5858
const filenameMatch = file.match(regex);
59-
let execFolder = ''
60-
let exeFile = ''
59+
let execFolder = "";
60+
let exeFile = "";
6161
if (!filenameMatch) {
6262
throw new Error("INVALID_FILEPATH");
6363
}
6464
const folderPath = path.resolve(__dirname, `../../temp`);
6565
if (language === languageType.C) {
66-
execFolder = path.resolve(folderPath, 'exe-c')
67-
exeFile = `${execFolder}/${filenameMatch}`
66+
execFolder = path.resolve(folderPath, "exe-c");
67+
exeFile = `${execFolder}/${filenameMatch}`;
6868
if (!fs.existsSync(execFolder)) {
6969
fs.mkdirSync(execFolder, { recursive: true });
7070
}
71-
execSync(
72-
`gcc -w -std=c++14 ${filePath} -o ${exeFile}`,
73-
);
71+
execSync(`gcc -w -std=c++14 ${filePath} -o ${exeFile}`);
7472
} else if (language === languageType.CPP) {
75-
execFolder = path.resolve(folderPath, 'exe-cpp')
76-
exeFile = `${execFolder}/${filenameMatch}`
73+
execFolder = path.resolve(folderPath, "exe-cpp");
74+
exeFile = `${execFolder}/${filenameMatch}`;
7775
if (!fs.existsSync(execFolder)) {
7876
fs.mkdirSync(execFolder, { recursive: true });
7977
}
80-
execSync(
81-
`g++ -w -std=c++14 ${filePath} -o ${exeFile}`,
82-
);
78+
execSync(`g++ -w -std=c++14 ${filePath} -o ${exeFile}`);
8379
} else if (language === languageType.JAVA) {
84-
execFolder = path.resolve(folderPath, 'exe-java')
85-
exeFile = `${execFolder}/${filenameMatch}.class`
80+
execFolder = path.resolve(folderPath, "exe-java");
81+
exeFile = `${execFolder}/${filenameMatch}.class`;
8682
if (!fs.existsSync(execFolder)) {
8783
fs.mkdirSync(execFolder, { recursive: true });
8884
}
8985
execSync(`javac -d ${execFolder} ${filePath}`);
9086
} else if (language === languageType.PYTHON) {
91-
exeFile = `${filePath}`
87+
exeFile = `${filePath}`;
9288
}
9389
return { result: "", exeFile: exeFile };
9490
} catch (error: any) {
9591
const err = error.stdout.toString()
9692
? error.stdout.toString()
9793
: error.stderr.toString();
94+
console.log(err);
9895
return { result: err, exeFile: "" };
9996
}
10097
},
@@ -120,45 +117,51 @@ export const compilerService = {
120117
file: string,
121118
): Promise<ExecutionResult> => {
122119
return new Promise(async (resolve, _reject) => {
123-
const inputFile = `${sanboxPath.toString().trim()}/input.txt`
124-
const outputFile = `${sanboxPath.toString().trim()}/output.txt`
125-
const metaFile = `${sanboxPath.toString().trim()}/meta.txt`
126-
writeFileSync(inputFile, input)
127-
writeFileSync(outputFile, '')
128-
writeFileSync(metaFile, '')
120+
const inputFile = `${sanboxPath.toString().trim()}/input.txt`;
121+
const outputFile = `${sanboxPath.toString().trim()}/output.txt`;
122+
const metaFile = `${sanboxPath.toString().trim()}/meta.txt`;
123+
writeFileSync(inputFile, input);
124+
writeFileSync(outputFile, "");
125+
writeFileSync(metaFile, "");
129126
try {
130127
const filenameMatch = file.match(/\w+/);
131-
let command = '';
128+
let command = "";
132129
if (language === languageType.C || language === languageType.CPP) {
133130
command = `isolate --box-id=${boxId} --time=5 --wall-time=5 --stderr-to-stdout --stdin=input.txt --stdout=output.txt --meta=${metaFile} --silent --run ${filenameMatch}`;
134131
} else if (language === languageType.JAVA) {
135-
command = `isolate --box-id=${boxId} --time=5 --wall-time=5 --stderr-to-stdout --stdin=input.txt --stdout=output.txt --meta=${metaFile} --silent --run /usr/lib/jvm/java-17-openjdk-amd64/bin/java ${filenameMatch}`;
132+
command = `isolate -p --box-id=${boxId} --time=5 --wall-time=5 --stderr-to-stdout --stdin=input.txt --stdout=output.txt --meta=${metaFile} --silent --run /usr/lib/jvm/java-17-openjdk-amd64/bin/java ${filenameMatch}`;
136133
} else if (language === languageType.PYTHON) {
137134
command = `isolate --box-id=${boxId} --time=5 --wall-time=5 --stderr-to-stdout --stdin=input.txt --stdout=output.txt --meta=${metaFile} --silent --run /usr/bin/python3 ${file}`;
138135
}
139136
const childProcess = spawn(command, { shell: true });
140137

141138
// Handle process exit
142-
childProcess.on('exit', () => {
143-
const metaContent = readFileSync(metaFile, 'utf-8');
144-
const output = readFileSync(outputFile, 'utf-8');
139+
childProcess.on("exit", () => {
140+
const metaContent = readFileSync(metaFile, "utf-8");
141+
const output = readFileSync(outputFile, "utf-8");
145142

146-
const lines = metaContent.split('\n');
147-
const status = lines.find((line) => line.startsWith('status:'))?.split(':')[1]?.trim() || '';
148-
const exitCode = lines.find((line) => line.startsWith('exitCode:'))?.split(':')[1]?.trim() || '';
143+
const lines = metaContent.split("\n");
144+
const status =
145+
lines
146+
.find((line) => line.startsWith("status:"))
147+
?.split(":")[1]
148+
?.trim() || "";
149+
const exitCode =
150+
lines
151+
.find((line) => line.startsWith("exitCode:"))
152+
?.split(":")[1]
153+
?.trim() || "";
149154

150-
if (status === 'TO') {
151-
resolve({ result: 'Execution Time Out' });
152-
} else if (exitCode !== '0') {
155+
if (status === "TO") {
156+
resolve({ result: "Execution Time Out" });
157+
} else if (exitCode !== "0") {
153158
resolve({ result: output });
154159
} else {
155160
resolve({ result: output });
156161
}
157-
158162
});
159-
160163
} catch (error) {
161-
resolve({ result: 'error execute' });
164+
resolve({ result: "error execute" });
162165
}
163166
});
164167
},

src/services/rabbitmq.service.ts

Lines changed: 76 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import client, { Connection, Channel, ConsumeMessage } from "amqplib";
22
import { environment } from "../config/environment";
3-
import { IResultSubmission, ISubmissionLearnify, ISubmissionRequest } from "../interfaces/submission.interface";
3+
import {
4+
IResultSubmission,
5+
ISubmissionLearnify,
6+
ISubmissionRequest,
7+
} from "../interfaces/submission.interface";
48
import {
59
ICompileRequest,
610
languageType,
@@ -11,7 +15,7 @@ import { problemService } from "./problem.service";
1115
import { ITestCase } from "../interfaces/testcase.interface";
1216
import { submissionService } from "./submission.service";
1317
import { checkRedisHealth, publicTopic, redisClient } from "./redis.service";
14-
import logger from '../utils/logger.util'
18+
import logger from "../utils/logger.util";
1519

1620
export const rabbitMQService = {
1721
sendDataToQueue: async (queueName: string, data: any) => {
@@ -34,14 +38,14 @@ export const rabbitMQService = {
3438
const connection: Connection = await client.connect(
3539
`amqp://${environment.RMQUSER}:${environment.RMQPASS}@${environment.RMQHOST}:5672`,
3640
);
37-
await redisClient.connect()
41+
await redisClient.connect();
3842
if (await checkRedisHealth()) {
39-
logger.info("Redis Connected")
43+
logger.info("Redis Connected");
4044
}
4145
const channel: Channel = await connection.createChannel();
4246
await channel.assertQueue("compiler", { durable: true });
4347
await channel.assertQueue("submission", { durable: true });
44-
await channel.assertQueue("learnify-submission", { durable: true })
48+
await channel.assertQueue("learnify-submission", { durable: true });
4549

4650
channel.consume("submission", async (msg: ConsumeMessage | null) => {
4751
try {
@@ -66,29 +70,42 @@ export const rabbitMQService = {
6670
submission,
6771
testcases,
6872
);
69-
if ("status" in resultProblem) {
70-
const resultSubmit: IResultSubmission = await submissionService.submit(
71-
{
72-
problemId: submission.problemId,
73-
sourceCode: submission.sourceCode,
74-
results: resultProblem.result,
75-
stateSubmission: resultProblem.status ? "PASS" : "FAILED",
76-
},
77-
submission.token,
78-
);
7973

80-
redisClient.set(`submission-${resultSubmit.data.username}`, JSON.stringify({ submissionId: resultSubmit.data.submissionId }), { EX: 240 })
74+
if ("status" in resultProblem) {
75+
const resultSubmit: IResultSubmission =
76+
await submissionService.submit(
77+
{
78+
problemId: submission.problemId,
79+
sourceCode: submission.sourceCode,
80+
results: resultProblem.result,
81+
stateSubmission: resultProblem.status ? "PASS" : "FAILED",
82+
},
83+
submission.token,
84+
);
8185

82-
redisClient.set(`submissionState-${submission.username}`, "false", { EX: 240 })
86+
redisClient.set(
87+
`submission-${resultSubmit.data.username}`,
88+
JSON.stringify({ submissionId: resultSubmit.data.submissionId }),
89+
{ EX: 240 },
90+
);
8391

84-
publicTopic('submission', JSON.stringify({ submissionId: resultSubmit.data.submissionId, username: resultSubmit.data.username }))
92+
redisClient.set(`submissionState-${submission.username}`, "false", {
93+
EX: 240,
94+
});
8595

96+
publicTopic(
97+
"submission",
98+
JSON.stringify({
99+
submissionId: resultSubmit.data.submissionId,
100+
username: resultSubmit.data.username,
101+
}),
102+
);
86103
} else {
87104
throw new Error("Error To Submission File: " + resultProblem.result);
88105
}
89106
channel.ack(msg);
90107
} catch (error) {
91-
console.log(error)
108+
console.log(error);
92109
throw new Error("Error receiveData");
93110
}
94111
});
@@ -113,44 +130,53 @@ export const rabbitMQService = {
113130
updateFileName,
114131
);
115132

116-
await redisClient.set(`compiler-${data.username}`, JSON.stringify(outputResult), { EX: 240 })
117-
const updateOutputResult = { ...outputResult, username: data.username }
118-
publicTopic('compiler', JSON.stringify(updateOutputResult))
133+
await redisClient.set(
134+
`compiler-${data.username}`,
135+
JSON.stringify(outputResult),
136+
{ EX: 240 },
137+
);
138+
const updateOutputResult = { ...outputResult, username: data.username };
139+
publicTopic("compiler", JSON.stringify(updateOutputResult));
119140

120141
channel.ack(msg);
121142
} catch (error) {
122-
console.log(error)
143+
console.log(error);
123144
throw new Error("Error receiveData");
124145
}
125146
});
126147

127-
channel.consume("learnify-submission", async (msg: ConsumeMessage | null) => {
128-
try {
129-
if (!msg) {
130-
throw new Error("Invalid Incoming Message");
131-
}
132-
const submission: ISubmissionLearnify = JSON.parse(
133-
msg?.content.toString() as string,
134-
);
135-
const updateSourceCode = strip(submission.sourceCode);
136-
const updateFileName =
137-
submission.language === languageType.JAVA
138-
? submission.fileName
139-
: `${process.pid}`;
140-
submission.sourceCode = updateSourceCode;
141-
submission.fileName = updateFileName;
142-
const resultProblem = await resultService.outputResultWithTestCaseLeanify(submission)
143-
console.log(resultProblem)
144-
if ("status" in resultProblem) {
145-
// save to learnify database
146-
} else {
147-
throw new Error("Error To Submission File: " + resultProblem.result);
148+
channel.consume(
149+
"learnify-submission",
150+
async (msg: ConsumeMessage | null) => {
151+
try {
152+
if (!msg) {
153+
throw new Error("Invalid Incoming Message");
154+
}
155+
const submission: ISubmissionLearnify = JSON.parse(
156+
msg?.content.toString() as string,
157+
);
158+
const updateSourceCode = strip(submission.sourceCode);
159+
const updateFileName =
160+
submission.language === languageType.JAVA
161+
? submission.fileName
162+
: `${process.pid}`;
163+
submission.sourceCode = updateSourceCode;
164+
submission.fileName = updateFileName;
165+
const resultProblem =
166+
await resultService.outputResultWithTestCaseLeanify(submission);
167+
console.log(resultProblem);
168+
if ("status" in resultProblem) {
169+
// save to learnify database
170+
} else {
171+
throw new Error(
172+
"Error To Submission File: " + resultProblem.result,
173+
);
174+
}
175+
channel.ack(msg);
176+
} catch (error) {
177+
throw new Error("Error receiveData");
148178
}
149-
channel.ack(msg);
150-
} catch (error) {
151-
throw new Error("Error receiveData");
152-
}
153-
});
154-
179+
},
180+
);
155181
},
156182
};

0 commit comments

Comments
 (0)