|
1 | 1 | import * as fs from "fs" |
2 | 2 | import * as path from "path" |
3 | | -import { fileURLToPath } from "url" |
4 | | -import pMap from "p-map" |
| 3 | +import * as os from "os" |
5 | 4 |
|
| 5 | +import { v4 as uuidv4 } from "uuid" |
6 | 6 | import { build, filesystem, GluegunPrompt, GluegunToolbox } from "gluegun" |
7 | 7 | import { runTests } from "@vscode/test-electron" |
8 | 8 |
|
9 | | -import { type Language, languages, type Run, findRun, createRun, getTask } from "@benchmark/db" |
| 9 | +import { |
| 10 | + type Language, |
| 11 | + languages, |
| 12 | + type Run, |
| 13 | + findRun, |
| 14 | + createRun, |
| 15 | + getPendingTask, |
| 16 | + createPendingTask, |
| 17 | + getTask, |
| 18 | +} from "@benchmark/db" |
10 | 19 |
|
11 | | -const __dirname = path.dirname(fileURLToPath(import.meta.url)) |
12 | | -const extensionDevelopmentPath = path.resolve(__dirname, "..", "..", "..", "..") |
13 | | -const extensionTestsPath = path.resolve(extensionDevelopmentPath, "benchmark/packages/runner/dist") |
14 | | -const exercisesPath = path.resolve(extensionDevelopmentPath, "..", "exercises") |
| 20 | +import { __dirname, extensionDevelopmentPath, extensionTestsPath, exercisesPath } from "./paths.js" |
| 21 | +import { getExercises } from "./exercises.js" |
15 | 22 |
|
16 | 23 | export const isLanguage = (language: string): language is Language => languages.includes(language as Language) |
17 | 24 |
|
18 | 25 | const run = async (toolbox: GluegunToolbox) => { |
19 | 26 | const { config, prompt } = toolbox |
20 | 27 | const id = config.runId ? Number(config.runId) : undefined |
21 | | - let { language, exercise } = config |
| 28 | + const { language, exercise } = config |
22 | 29 |
|
23 | 30 | if (language === "all") { |
24 | | - const run = await findOrCreateRun({ id }) |
25 | | - await runAll(run) |
| 31 | + await runAll(id) |
26 | 32 | } else if (exercise === "all") { |
27 | | - const run = await findOrCreateRun({ id }) |
28 | | - await runLanguage({ run, language }) |
| 33 | + await runLanguage({ id, language }) |
29 | 34 | } else { |
30 | | - language = language || (await askLanguage(prompt)) |
31 | | - exercise = exercise || (await askExercise(prompt, language)) |
32 | | - const run = await findOrCreateRun({ id }) |
33 | | - await runExercise({ run, language, exercise }) |
| 35 | + await runLanguageExercise({ |
| 36 | + id, |
| 37 | + language: language || (await askLanguage(prompt)), |
| 38 | + exercise: exercise || (await askExercise(prompt, language)), |
| 39 | + }) |
34 | 40 | } |
35 | 41 | } |
36 | 42 |
|
37 | | -const runAll = async (run: Run) => |
38 | | - (await pMap(languages, (language) => runLanguage({ run, language }), { concurrency: 1 })).flatMap( |
39 | | - (language) => language, |
40 | | - ) |
| 43 | +const runAll = async (id?: number) => { |
| 44 | + const run = await findOrCreateRun({ id }) |
| 45 | + const exercises = getExercises() |
41 | 46 |
|
42 | | -const runLanguage = async ({ run, language }: { run: Run; language: Language }) => { |
43 | | - const languagePath = path.resolve(exercisesPath, language) |
| 47 | + for (const [language, languageExercises] of Object.entries(exercises)) { |
| 48 | + await Promise.all( |
| 49 | + languageExercises.map((exercise) => |
| 50 | + findOrCreatePendingTask({ runId: run.id, language: language as Language, exercise }), |
| 51 | + ), |
| 52 | + ) |
| 53 | + } |
44 | 54 |
|
45 | | - if (!fs.existsSync(languagePath)) { |
46 | | - console.error(`Language directory ${languagePath} does not exist`) |
47 | | - process.exit(1) |
| 55 | + for (const [language, languageExercises] of Object.entries(exercises)) { |
| 56 | + for (const exercise of languageExercises) { |
| 57 | + await runExercise({ run, language: language as Language, exercise }) |
| 58 | + } |
48 | 59 | } |
| 60 | +} |
49 | 61 |
|
50 | | - const exercises = filesystem |
51 | | - .subdirectories(languagePath) |
52 | | - .map((exercise) => path.basename(exercise)) |
53 | | - .filter((exercise) => !exercise.startsWith(".")) |
54 | | - |
55 | | - const results = await pMap( |
56 | | - exercises, |
57 | | - async (exercise) => ({ |
58 | | - language, |
59 | | - exercise, |
60 | | - result: await runExercise({ run, language, exercise }), |
61 | | - }), |
62 | | - { concurrency: 1 }, |
| 62 | +const runLanguage = async ({ id, language }: { id?: number; language: Language }) => { |
| 63 | + const run = await findOrCreateRun({ id }) |
| 64 | + const exercises = getExercises() |
| 65 | + const languageExercises = exercises[language] |
| 66 | + |
| 67 | + await Promise.all( |
| 68 | + languageExercises.map((exercise) => findOrCreatePendingTask({ runId: run.id, language, exercise })), |
63 | 69 | ) |
64 | 70 |
|
65 | | - return results |
| 71 | + for (const exercise of languageExercises) { |
| 72 | + await runExercise({ run, language, exercise }) |
| 73 | + } |
| 74 | +} |
| 75 | + |
| 76 | +const runLanguageExercise = async ({ |
| 77 | + id, |
| 78 | + language, |
| 79 | + exercise, |
| 80 | +}: { |
| 81 | + id?: number |
| 82 | + language: Language |
| 83 | + exercise: string |
| 84 | +}) => { |
| 85 | + const run = await findOrCreateRun({ id }) |
| 86 | + await findOrCreatePendingTask({ runId: run.id, language, exercise }) |
| 87 | + return runExercise({ run, language, exercise }) |
66 | 88 | } |
67 | 89 |
|
68 | 90 | const runExercise = async ({ run, language, exercise }: { run: Run; language: Language; exercise: string }) => { |
@@ -127,10 +149,20 @@ const askExercise = async (prompt: GluegunPrompt, language: Language) => { |
127 | 149 | return exercise |
128 | 150 | } |
129 | 151 |
|
130 | | -type FindOrCreateRun = { id?: number; model?: string } |
131 | | - |
132 | | -const findOrCreateRun = async ({ id, model = "anthropic/claude-3.7-sonnet" }: FindOrCreateRun) => |
133 | | - id ? findRun(id) : createRun({ model }) |
| 152 | +const findOrCreateRun = async ({ id, model = "anthropic/claude-3.7-sonnet" }: { id?: number; model?: string }) => |
| 153 | + id |
| 154 | + ? findRun(id) |
| 155 | + : createRun({ model, pid: process.pid, socketPath: path.resolve(os.tmpdir(), `benchmark-${uuidv4()}.sock`) }) |
| 156 | + |
| 157 | +const findOrCreatePendingTask = async ({ |
| 158 | + runId, |
| 159 | + language, |
| 160 | + exercise, |
| 161 | +}: { |
| 162 | + runId: number |
| 163 | + language: Language |
| 164 | + exercise: string |
| 165 | +}) => (await getPendingTask({ runId, language, exercise })) || (await createPendingTask({ runId, language, exercise })) |
134 | 166 |
|
135 | 167 | const main = async () => { |
136 | 168 | const cli = build() |
|
0 commit comments