feat:优化代码 enhancedmultiFileRunner.ts
This commit is contained in:
parent
4d5288ed33
commit
2375707515
@ -1,11 +1,12 @@
|
|||||||
'use server';
|
'use server';
|
||||||
|
|
||||||
import Docker from 'dockerode';
|
import Docker from 'dockerode';
|
||||||
import fs from 'fs';
|
import fs from 'fs/promises'; // 使用异步版本的 fs 模块
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
const docker = new Docker();
|
const docker = new Docker();
|
||||||
|
const DOCKER_IMAGE_URL = process.env.DOCKER_IMAGE_URL || 'fly6516.synology.me:8080/multilang:latest'; // 使用环境变量
|
||||||
|
|
||||||
let giteaRepoUrl: string | undefined;
|
let giteaRepoUrl: string | undefined;
|
||||||
let giteaToken: string | undefined;
|
let giteaToken: string | undefined;
|
||||||
@ -55,7 +56,7 @@ const fetchFilesFromGitea = async (dir: string, tempDir: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const targetDir = path.join(tempDir, dir);
|
const targetDir = path.join(tempDir, dir);
|
||||||
fs.mkdirSync(targetDir, { recursive: true });
|
await fs.mkdir(targetDir, { recursive: true });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`${giteaRepoUrl}/contents/${dir}`, {
|
const response = await axios.get(`${giteaRepoUrl}/contents/${dir}`, {
|
||||||
@ -69,19 +70,18 @@ const fetchFilesFromGitea = async (dir: string, tempDir: string) => {
|
|||||||
throw new Error(`Invalid directory structure for ${dir} in repository.`);
|
throw new Error(`Invalid directory structure for ${dir} in repository.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const file of files) {
|
// 并行下载文件
|
||||||
if (file.type === 'file') {
|
await Promise.all(files.filter(file => file.type === 'file').map(async (file) => {
|
||||||
const fileResponse = await axios.get(file.download_url, {
|
const fileResponse = await axios.get(file.download_url, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `token ${giteaToken}`,
|
Authorization: `token ${giteaToken}`,
|
||||||
},
|
},
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
});
|
});
|
||||||
|
|
||||||
const filePath = path.join(targetDir, file.name);
|
const filePath = path.join(targetDir, file.name);
|
||||||
fs.writeFileSync(filePath, fileResponse.data);
|
await fs.writeFile(filePath, fileResponse.data);
|
||||||
}
|
}));
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`Failed to fetch files from '${dir}': ${(error as Error).message}`);
|
throw new Error(`Failed to fetch files from '${dir}': ${(error as Error).message}`);
|
||||||
}
|
}
|
||||||
@ -93,10 +93,14 @@ const fetchFilesFromGitea = async (dir: string, tempDir: string) => {
|
|||||||
* @param expectedFilePath 正确答案文件路径
|
* @param expectedFilePath 正确答案文件路径
|
||||||
* @returns 是否一致的比较结果
|
* @returns 是否一致的比较结果
|
||||||
*/
|
*/
|
||||||
const compareResults = (resultFilePath: string, expectedFilePath: string): boolean => {
|
const compareResults = async (resultFilePath: string, expectedFilePath: string): Promise<boolean> => {
|
||||||
const result = fs.readFileSync(resultFilePath, 'utf-8').trim();
|
try {
|
||||||
const expected = fs.readFileSync(expectedFilePath, 'utf-8').trim();
|
const result = (await fs.readFile(resultFilePath, 'utf-8')).trim();
|
||||||
return result === expected;
|
const expected = (await fs.readFile(expectedFilePath, 'utf-8')).trim();
|
||||||
|
return result === expected;
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Failed to read files for comparison: ${(error as Error).message}`);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,14 +134,14 @@ export const runMultiFileCodeWithOptionalTestData = async (params: {
|
|||||||
: 'python3 script.py';
|
: 'python3 script.py';
|
||||||
|
|
||||||
const tempDir = path.join('/tmp', `${Date.now()}`);
|
const tempDir = path.join('/tmp', `${Date.now()}`);
|
||||||
fs.mkdirSync(tempDir, { recursive: true });
|
await fs.mkdir(tempDir, { recursive: true });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 写入代码文件
|
// 写入代码文件
|
||||||
for (const file of files) {
|
await Promise.all(files.map(async (file) => {
|
||||||
const filePath = path.join(tempDir, file.name);
|
const filePath = path.join(tempDir, file.name);
|
||||||
fs.writeFileSync(filePath, file.content);
|
await fs.writeFile(filePath, file.content);
|
||||||
}
|
}));
|
||||||
|
|
||||||
// 检查是否设置了 Gitea 仓库信息
|
// 检查是否设置了 Gitea 仓库信息
|
||||||
if (giteaRepoUrl && giteaToken) {
|
if (giteaRepoUrl && giteaToken) {
|
||||||
@ -152,7 +156,7 @@ export const runMultiFileCodeWithOptionalTestData = async (params: {
|
|||||||
|
|
||||||
// 创建 Docker 容器
|
// 创建 Docker 容器
|
||||||
const container = await docker.createContainer({
|
const container = await docker.createContainer({
|
||||||
Image: 'fly6516.synology.me:8080/multilang:latest',
|
Image: DOCKER_IMAGE_URL,
|
||||||
Cmd: ['sh', '-c', compileAndRunCmd],
|
Cmd: ['sh', '-c', compileAndRunCmd],
|
||||||
AttachStdout: true,
|
AttachStdout: true,
|
||||||
AttachStderr: true,
|
AttachStderr: true,
|
||||||
@ -180,14 +184,14 @@ export const runMultiFileCodeWithOptionalTestData = async (params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果指定了结果输出文件和正确答案文件,执行比较
|
// 如果指定了结果输出文件和正确答案文件,执行比较
|
||||||
if (resultOutputFile && expectedAnswerFiles) {
|
if (resultOutputFile && expectedAnswerFiles && expectedAnswerFiles.length > 0) {
|
||||||
const resultFilePath = path.join(tempDir, resultOutputFile);
|
const resultFilePath = path.join(tempDir, resultOutputFile);
|
||||||
|
|
||||||
const comparisonResults = expectedAnswerFiles.map((expectedFile) => {
|
const comparisonResults = await Promise.all(expectedAnswerFiles.map(async (expectedFile) => {
|
||||||
const expectedFilePath = path.join(tempDir, testDataPath, expectedFile);
|
const expectedFilePath = path.join(tempDir, testDataPath, expectedFile);
|
||||||
const isMatch = compareResults(resultFilePath, expectedFilePath);
|
const isMatch = await compareResults(resultFilePath, expectedFilePath);
|
||||||
return { expectedFile, isMatch };
|
return { expectedFile, isMatch };
|
||||||
});
|
}));
|
||||||
|
|
||||||
return { output, comparisonResults };
|
return { output, comparisonResults };
|
||||||
}
|
}
|
||||||
@ -196,6 +200,6 @@ export const runMultiFileCodeWithOptionalTestData = async (params: {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { error: `An error occurred: ${(error as Error).message}` };
|
return { error: `An error occurred: ${(error as Error).message}` };
|
||||||
} finally {
|
} finally {
|
||||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
await fs.rm(tempDir, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user