Skip to content

Commit 8408325

Browse files
committed
Merge branch 'master' into runModes
2 parents 3f94608 + 0417291 commit 8408325

File tree

6 files changed

+51
-7
lines changed

6 files changed

+51
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,4 @@ fabric.properties
115115

116116
# Config
117117
secrets.json
118+
.vscode

Dockerfile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ FROM node:8-alpine
33
WORKDIR /usr/src/judge-api
44

55
COPY package.json .
6-
COPY package-lock.json .
7-
86
RUN npm install -D
97

108
COPY . .
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
alter table submissions
2-
add column outputs varchar[];
1+
alter table submissions add column outputs varchar[];

src/routes/api/run.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {SubmissionAttributes, Submissions, db} from '../../db/models'
55
import {RunJob, queueJob, successListener} from '../../rabbitmq/jobqueue'
66
import {isInvalidRunRequest} from '../../validators/SubmissionValidators'
77
import {upload} from '../../utils/s3'
8+
import {normalizeRunJob} from '../../utils'
89
import config = require('../../../config')
910

1011
const route: Router = Router()
@@ -111,6 +112,7 @@ const getRunPoolElement = function (body: RunRequestBody, res: Response): RunPoo
111112
* @apiParam {String(Base64)} input [Optional] stdin input for the program (encoded in base64)
112113
* @apiParam {Enum} mode [Optional] mode for request. Default = `sync`, see: https://github.com/coding-blocks/judge-api/issues/16
113114
* @apiParam {String)} callback [Optional] callback url for request. Required for `mode = callback`
115+
* @apiParam {String)} enc [Optional] Encoding type for stdin and source. Can be `url`|`base64`. Default = 'base64'
114116
*
115117
* @apiUse AvailableLangs
116118
*
@@ -153,14 +155,16 @@ route.post('/', (req, res, next) => {
153155
Submissions.create(<SubmissionAttributes>{
154156
lang: req.body.lang,
155157
start_time: new Date()
156-
}).then((submission: SubmissionAttributes) => {
158+
}).then(async (submission: SubmissionAttributes) => {
157159

158-
let queued = queueJob(<RunJob>{
160+
const job: RunJob = await normalizeRunJob({
159161
id: submission.id,
160162
source: req.body.source,
161163
lang: req.body.lang,
162164
stdin: req.body.stdin
163-
})
165+
}, req.body.enc)
166+
167+
let queued = queueJob(job)
164168

165169
// Put into pool and wait for judge-worker to respond
166170
runPool[submission.id] = getRunPoolElement(req.body, res)

src/utils/index.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {RunJob} from '../rabbitmq/jobqueue'
2+
import {download} from './s3'
3+
4+
/**
5+
* Normalizes the Run Job (effectively normalizes source and stdin to base64 immediate values)
6+
* @param {RunJob} job
7+
* @param {string} enc (Default = 'base64')
8+
* @returns {Promise<RunJob>} the normalized runJob
9+
*/
10+
export const normalizeRunJob = async function (job: RunJob, enc:string = 'base64') : Promise<RunJob> {
11+
switch (enc) {
12+
case 'url':
13+
const [source, stdin] = await Promise.all([download(job.source), download(job.stdin)])
14+
return {
15+
...job,
16+
source,
17+
stdin
18+
}
19+
default: return job
20+
}
21+
}

src/utils/s3.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Minio = require('minio')
22
import v4 = require('uuid/v4')
3+
import axios from 'axios'
34
import config = require('../../config')
45

56
const client = new Minio.Client({
@@ -17,11 +18,31 @@ export type savedFile = {
1718

1819
export const urlForFilename = (bucket: string, filename: string) : string => `http${config.S3.ssl ? 's': ''}://${config.S3.endpoint}/${bucket}/${filename}`
1920

21+
/**
22+
* Uploads an object to s3 encoded as json
23+
* @param {object} object
24+
* @param {string} filename The filename (Default = randomized)
25+
* @param {string} bucket The bucket name (Default = picked from config.json)
26+
* @returns {Promise<savedFile>} The etag and url for the file saved
27+
*/
2028
export const upload = function (object:object, filename:string = v4() + '.json' ,bucket:string = config.S3.bucket) : Promise<savedFile> {
2129
return new Promise((resolve, reject) => {
2230
client.putObject(bucket, filename, JSON.stringify(object), function(err, etag) {
2331
if (err) return reject(err)
2432
resolve({etag, url: urlForFilename(bucket, filename) })
2533
})
2634
})
35+
}
36+
37+
/**
38+
* Downloads a file from url and encodes it
39+
* @param {string} url
40+
* @param {string} enc (Default = 'base64')
41+
* @returns {Promise<string>} the downloaded file encoded as specified
42+
*/
43+
export const download = async function (url: string, enc: string = 'base64') : Promise<string> {
44+
if (!url) return ''
45+
46+
const {data} = await axios.get(url)
47+
return Buffer.from(data).toString(enc)
2748
}

0 commit comments

Comments
 (0)