Skip to content

Commit

Permalink
Merge pull request #43 from prabalsingh24/project-worker-prabal
Browse files Browse the repository at this point in the history
feature: ProjectWorker
  • Loading branch information
jatinkatyal13 authored May 25, 2020
2 parents 78a3cbb + 9a24b9e commit 9fa1620
Show file tree
Hide file tree
Showing 30 changed files with 163 additions and 90 deletions.
7 changes: 6 additions & 1 deletion src/taskmaster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import * as amqp from 'amqplib/callback_api'
import {Connection} from 'amqplib/callback_api'
import { execute } from './tasks'
import config = require('../config.js')
import { SubmitJob, RunJob } from 'tasks/job';
import {SubmitJob} from './tasks/jobs/submission';
import {ProjectJob} from './tasks/jobs/project';
import {RunJob} from './tasks/jobs/run';
import { mkdir } from 'shelljs'

// =============== Setup Raven
Expand Down Expand Up @@ -41,6 +43,9 @@ amqp.connect(`amqp://${config.AMQP.USER}:${config.AMQP.PASS}@${config.AMQP.HOST}
case 'run':
job = new RunJob(payload)
break
case 'project':
job = new ProjectJob(payload)
break
default:
throw new Error("Scenario not declared")
}
Expand Down
11 changes: 9 additions & 2 deletions src/tasks/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { Result, RunResult, SubmissionResult } from 'types/result'
import { Result, RunResult, SubmissionResult, ProjectResult } from 'types/result'
import config = require('../../config.js')
import {exec, mkdir, rm} from 'shelljs'
import * as path from 'path'

import RunScenario from './scenarios/run'
import SubmissionScenario from './scenarios/submission'
import { RunJob, SubmitJob, Job } from "./job";
import ProjectScenario from './scenarios/project'
import {Job } from './job'
import {RunJob} from './jobs/run'
import {SubmitJob} from './jobs/submission';
import {ProjectJob} from './jobs/project';

export function execute(job: RunJob): Promise<RunResult>
export function execute(job: SubmitJob): Promise<SubmissionResult>
export function execute(job: ProjectJob): Promise<ProjectResult>
export async function execute (job: Job) {
// Create RUNBOX
const currentJobDir = path.join(config.RUNBOX.DIR, job.id.toString())
Expand All @@ -19,6 +24,8 @@ export async function execute (job: Job) {
scenario = new RunScenario()
} else if (job instanceof SubmitJob) {
scenario = new SubmissionScenario()
} else if (job instanceof ProjectJob) {
scenario = new ProjectScenario()
}

// Setup RUNBOX
Expand Down
42 changes: 1 addition & 41 deletions src/tasks/job.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,10 @@
interface JobConstructorOpts {
export interface JobConstructorOpts {
id: number
source: string
lang: string
scenario: "run" | "submit" | "project"
timelimit?: number
}
interface RunJobConstructorOpts extends JobConstructorOpts {
stdin: string
}
interface TestcaseOpts {
id: number,
input: string,
output: string
}
interface SubmitJobConstructorOpts extends JobConstructorOpts {
testcases: Array<TestcaseOpts>
}

interface ProjectConstructorOpts extends JobConstructorOpts {
problem: string
}

export class Job {
id: number
Expand All @@ -37,29 +22,4 @@ export class Job {
}
}

export class RunJob extends Job {
stdin: string

constructor({ id, source, lang, timelimit, scenario, stdin }: RunJobConstructorOpts) {
super({id, source, lang, timelimit, scenario})
this.stdin = stdin
}
}

export class SubmitJob extends Job {
testcases: Array<TestcaseOpts>

constructor({ id, source, lang, timelimit, scenario, testcases }: SubmitJobConstructorOpts) {
super({id, source, lang, timelimit, scenario})
this.testcases = testcases
}
}

export class ProjectJob extends Job {
problem: string

constructor({ id, source, lang, timelimit, scenario, problem}: ProjectConstructorOpts) {
super({ id, source, lang, timelimit, scenario})
this.problem = problem
}
}
16 changes: 16 additions & 0 deletions src/tasks/jobs/project.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {Job, JobConstructorOpts} from '../job';

interface ProjectConstructorOpts extends JobConstructorOpts {
problem: string,
submissionDirs: string
}
export class ProjectJob extends Job {
problem: string
submissionDirs: string

constructor({ id, source, lang, timelimit, scenario, problem, submissionDirs}: ProjectConstructorOpts) {
super({ id, source, lang, timelimit, scenario})
this.problem = problem
this.submissionDirs = submissionDirs
}
}
14 changes: 14 additions & 0 deletions src/tasks/jobs/run.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {Job, JobConstructorOpts} from '../job';

interface RunJobConstructorOpts extends JobConstructorOpts {
stdin: string
}

export class RunJob extends Job {
stdin: string

constructor({ id, source, lang, timelimit, scenario, stdin }: RunJobConstructorOpts) {
super({id, source, lang, timelimit, scenario})
this.stdin = stdin
}
}
20 changes: 20 additions & 0 deletions src/tasks/jobs/submission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {Job, JobConstructorOpts} from '../job';

interface TestcaseOpts {
id: number,
input: string,
output: string
}

interface SubmitJobConstructorOpts extends JobConstructorOpts {
testcases: Array<TestcaseOpts>
}

export class SubmitJob extends Job {
testcases: Array<TestcaseOpts>

constructor({ id, source, lang, timelimit, scenario, testcases }: SubmitJobConstructorOpts) {
super({id, source, lang, timelimit, scenario})
this.testcases = testcases
}
}
70 changes: 56 additions & 14 deletions src/tasks/scenarios/project.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,74 @@
import config = require('../../../config.js')
import {cat, exec, mkdir, rm, touch, head} from 'shelljs'
import { ProjectJob } from 'tasks/job'
import { cat, exec, mkdir} from 'shelljs'
import { ProjectJob } from '../jobs/project'
import { ProjectResult } from 'types/result'
import * as path from 'path'
import * as fs from 'fs'
import { Scenario } from 'tasks/scenario'
import { download } from 'utils/request'

export default class ProjectScenario extends Scenario {
async setup(currentJobDir: string, job: ProjectJob) {
// TODO
const problemDir = path.join(currentJobDir, job.problem)
await download(job.problem, problemDir)
const problemZipDir = path.join(currentJobDir, 'problem.zip')
const solutionZipDir = path.join(currentJobDir, 'solution.zip')
await download(job.problem, problemZipDir)
await download(job.source, solutionZipDir)

const solutionDir = path.join(currentJobDir, job.source)
await download(job.problem, solutionDir)
const problemDir = path.join(currentJobDir, 'problem')
mkdir('-p', problemDir)
exec(`unzip ${problemZipDir} -d ${problemDir}`)

const solutionDir = path.join(currentJobDir, 'solution')
mkdir('-p', solutionDir)
exec(`unzip ${solutionZipDir} -d ${solutionDir}`)
}

run(currentJobDir: string, job: ProjectJob) {
const PROJECT_CONFIG = config.PROJECT[job.lang]
return exec(`docker run \\
--cpus="${PROJECT_CONFIG.CPU_SHARE}" \\
--memory="${PROJECT_CONFIG.MEM_LIMIT}" \\
--rm \\
-v "${currentJobDir}":/usr/src/runbox \\
-w /usr/src/runbox codingblocks/project-worker-"${job.lang}" \\
/bin/judge.sh -s "${job.submissionDirs}"
`);
}

async result(currentJobDir: string, job: ProjectJob): Promise<ProjectResult> {
// TODO
const result_code = cat(path.join(currentJobDir, 'result.code')).toString()
if (result_code === '25') {
//problem hash and solution hash were not equal
return {
id: job.id,
stderr: cat(path.join(currentJobDir, 'result.stderr')).toString(),
stdout: '',
code: parseInt(result_code),
time: 0,
score: 0
}
}

const build_stderr = cat(path.join(currentJobDir, 'build.stderr')).toString()
const result_time = cat(path.join(currentJobDir, 'result.time').toString()) || '0'

if (build_stderr) {
return {
id: job.id,
stderr: build_stderr,
stdout: '',
code: parseInt(result_code),
time: parseFloat(result_time),
score: 0
}
}

return {
id: job.id,
stderr: '',
stdout: '',
time: 0,
code: 0,
score: 0
stderr: cat((path.join(currentJobDir, 'run.stderr')).toString()),
stdout: cat(path.join(currentJobDir, 'run.stdout')).toString(),
code: parseInt(result_code),
time: parseFloat(result_time),
score: parseInt(result_code) === 0 ? 100 : 0
}
}
}
4 changes: 2 additions & 2 deletions src/tasks/scenarios/run.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import config = require('../../../config.js')
import {cat, exec, mkdir, rm, touch, head} from 'shelljs'
import { RunJob } from '../job'
import { cat, exec, mkdir, rm, touch, head } from 'shelljs'
import { RunJob} from '../jobs/run'
import { RunResult } from 'types/result'
import * as path from 'path'
import * as fs from 'fs'
Expand Down
2 changes: 1 addition & 1 deletion src/tasks/scenarios/submission.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import config = require('../../../config.js')
import { cat, ls, mkdir, exec } from 'shelljs'
import { SubmitJob } from 'tasks/job'
import { SubmitJob } from '../jobs/submission'
import { SubmissionResult } from 'types/result'
import * as path from 'path'
import * as fs from 'fs'
Expand Down
3 changes: 2 additions & 1 deletion test/run/run.c.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {execute} from '../../src/tasks/'
import {expect} from 'chai'
import { RunJob } from '../../src/tasks/job'
import {RunJob} from '../../src/tasks/jobs/run'

describe('run - c', () => {
it('.c file runs correctly', async () => {
const runResult = await execute(new RunJob({
Expand Down
3 changes: 2 additions & 1 deletion test/run/run.cpp.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {execute} from '../../src/tasks/'
import {expect} from 'chai'
import { RunJob } from '../../src/tasks/job'
import {RunJob} from '../../src/tasks/jobs/run'


describe('run - cpp', () => {
it('.cpp file runs correctly', async () => {
Expand Down
3 changes: 2 additions & 1 deletion test/run/run.csharp.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {execute} from '../../src/tasks/'
import {expect} from 'chai'
import { RunJob } from '../../src/tasks/job'
import {RunJob} from '../../src/tasks/jobs/run'


describe('run - csharp', () => {
it('.cs file runs correctly', async () => {
Expand Down
3 changes: 2 additions & 1 deletion test/run/run.java8.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {execute} from '../../src/tasks/'
import {expect} from 'chai'
import { RunJob } from '../../src/tasks/job'
import {RunJob} from '../../src/tasks/jobs/run'


describe('run - java8', () => {
it('.java file runs correctly (Java8)', async () => {
Expand Down
3 changes: 2 additions & 1 deletion test/run/run.nodejs10.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {execute} from '../../src/tasks/'
import {expect} from 'chai'
import { RunJob } from '../../src/tasks/job'
import {RunJob} from '../../src/tasks/jobs/run'

describe('run - nodejs10', () => {
it('.js file runs correctly (NodeJS 6)', async () => {
const runResult = await execute(new RunJob({
Expand Down
3 changes: 2 additions & 1 deletion test/run/run.nodejs8.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {execute} from '../../src/tasks/'
import {expect} from 'chai'
import { RunJob } from '../../src/tasks/job'
import {RunJob} from '../../src/tasks/jobs/run'


describe('run - nodejs8', () => {
it('.js file runs correctly (NodeJS 8)', async () => {
Expand Down
3 changes: 2 additions & 1 deletion test/run/run.py2.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {execute} from '../../src/tasks/'
import {expect} from 'chai'
import { RunJob } from '../../src/tasks/job'
import {RunJob} from '../../src/tasks/jobs/run'


describe('run - py2', () => {
it('.py file runs correctly (Python 2.7)', async () => {
Expand Down
3 changes: 2 additions & 1 deletion test/run/run.py3.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {execute} from '../../src/tasks/'
import {expect} from 'chai'
import { RunJob } from '../../src/tasks/job'
import {RunJob} from '../../src/tasks/jobs/run'


describe('run - py3', () => {
it('.py file runs correctly (Python 3.0)', async () => {
Expand Down
3 changes: 2 additions & 1 deletion test/run/run.ruby.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {execute} from '../../src/tasks/'
import {expect} from 'chai'
import { RunJob } from '../../src/tasks/job'
import {RunJob} from '../../src/tasks/jobs/run'


describe('run - ruby', () => {
it('.rb file runs correctly', async () => {
Expand Down
18 changes: 9 additions & 9 deletions test/scenarios/projectScenario.spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { expect } from 'chai'
import { ProjectJob } from '../../src/tasks/job'
import { ProjectJob } from '../../src/tasks/jobs/project';
import ProjectScenarion from '../../src/tasks/scenarios/project'

describe('Project Scenario', () => {
it('should setup', async () => {
const job: ProjectJob = {
id: 1,
source: '',
lang: 'nodejs',
timelimit: 20,
scenario: 'problem',
problem: ''
}
// const job: ProjectJob = {
// id: 1,
// source: '',
// lang: 'nodejs',
// timelimit: 20,
// scenario: 'problem',
// problem: ''
// }
})
})
2 changes: 1 addition & 1 deletion test/scenarios/runScenario.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { mkdir, rm } from 'shelljs'
import RunScenario from '../../src/tasks/scenarios/run'
import config = require('../../config.js')
import * as path from 'path'
import { RunJob } from '../../src/tasks/job'
import {RunJob} from '../../src/tasks/jobs/run'
import * as fs from 'fs'

describe('Run Scenario', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/scenarios/submissionScenario.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { mkdir, rm } from 'shelljs'
import config = require('../../config.js')
import * as path from 'path'
import SubmissionScenario from '../../src/tasks/scenarios/submission'
import { SubmitJob } from '../../src/tasks/job'
import { SubmitJob } from '../../src/tasks/jobs/submission'

describe('Submission Scenario', () => {
it('should setup', async () => {
Expand Down
Loading

0 comments on commit 9fa1620

Please sign in to comment.