chore(xo-server): handle nested job props (#2712)

This commit is contained in:
Julien Fontanet 2018-03-02 19:29:08 +01:00 committed by GitHub
parent e76a0ad4bd
commit 48b2297bc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 64 additions and 73 deletions

View File

@ -8,7 +8,7 @@ getAll.permission = 'admin'
getAll.description = 'Gets all available jobs'
export async function get (id) {
return /* await */ this.getJob(id)
return /* await */ this.getJob(id, 'call')
}
get.permission = 'admin'

View File

@ -1,43 +0,0 @@
import Collection from '../collection/redis'
import Model from '../model'
import { forEach } from '../utils'
import { parseProp } from './utils'
// ===================================================================
export default class Job extends Model {}
export class Jobs extends Collection {
get Model () {
return Job
}
async create (job) {
// Serializes.
job.paramsVector = JSON.stringify(job.paramsVector)
return /* await */ this.add(new Job(job))
}
async save (job) {
// Serializes.
job.paramsVector = JSON.stringify(job.paramsVector)
return /* await */ this.update(job)
}
async get (properties) {
const jobs = await super.get(properties)
// Deserializes.
forEach(jobs, job => {
job.paramsVector = parseProp('job', job, 'paramsVector', {})
const { timeout } = job
if (timeout !== undefined) {
job.timeout = +timeout
}
})
return jobs
}
}

View File

@ -0,0 +1,15 @@
// @flow
// patch o: assign properties from p
// if the value of a p property is null, delete it from o
const patch = <T: {}>(o: T, p: $Shape<T>) => {
Object.keys(p).forEach(k => {
const v: any = p[k]
if (v === null) {
delete o[k]
} else if (v !== undefined) {
o[k] = v
}
})
}
export { patch as default }

View File

@ -2,13 +2,12 @@
import type { Pattern } from 'value-matcher'
// $FlowFixMe
import { assign } from 'lodash'
// $FlowFixMe
import { cancelable } from 'promise-toolbox'
import { noSuchObject } from 'xo-common/api-errors'
import { Jobs as JobsDb } from '../../models/job'
import Collection from '../../collection/redis'
import patch from '../../patch'
import { mapToArray, serializeError } from '../../utils'
import type Logger from '../logs/loggers/abstract'
@ -66,7 +65,46 @@ export type Executor = ({|
runJobId: string,
schedule?: Schedule,
session: Object
|}) => Promise<void>
|}) => Promise<any>
// -----------------------------------------------------------------------------
const normalize = job => {
Object.keys(job).forEach(key => {
try {
job[key] = JSON.parse(job[key])
} catch (_) {}
})
return job
}
const serialize = (job: {| [string]: any |}) => {
Object.keys(job).forEach(key => {
const value = job[key]
if (typeof value !== 'string') {
job[key] = JSON.stringify(job[key])
}
})
return job
}
class JobsDb extends Collection {
async create (job): Promise<Job> {
return normalize((await this.add(serialize((job: any)))).properties)
}
async save (job): Promise<void> {
await this.update(serialize((job: any)))
}
async get (): Promise<Array<Job>> {
const jobs = await super.get()
jobs.forEach(normalize)
return jobs
}
}
// -----------------------------------------------------------------------------
export default class Jobs {
_app: any
@ -116,29 +154,22 @@ export default class Jobs {
return result
}
async getJob (id: string, type: string = 'call'): Promise<Job> {
async getJob (id: string, type?: string): Promise<Job> {
const job = await this._jobs.first(id)
if (job === null || job.type !== type) {
if (job === null || (type !== undefined && job.properties.type !== type)) {
throw noSuchObject(id, 'job')
}
return job.properties
}
async createJob (job: $Diff<Job, {| id: string |}>): Promise<Job> {
// TODO: use plain objects
const job_ = await this._jobs.create(job)
return job_.properties
createJob (job: $Diff<Job, {| id: string |}>): Promise<Job> {
return this._jobs.create(job)
}
async updateJob ({ id, ...props }: $Shape<Job>) {
const job = await this.getJob(id)
assign(job, props)
if (job.timeout === null) {
delete job.timeout
}
patch(job, props)
return /* await */ this._jobs.save(job)
}

View File

@ -4,6 +4,7 @@ import { createSchedule } from '@xen-orchestra/cron'
import { noSuchObject } from 'xo-common/api-errors'
import Collection from '../collection/redis'
import patch from '../patch'
import { asyncMap } from '../utils'
export type Schedule = {|
@ -36,19 +37,6 @@ class Schedules extends Collection {
}
}
// patch o: assign properties from p
// if the value of a p property is null, delete it from o
const patch = <T: {}>(o: T, p: $Shape<T>) => {
Object.keys(p).forEach(k => {
const v: any = p[k]
if (v === null) {
delete o[k]
} else if (v !== undefined) {
o[k] = v
}
})
}
export default class Scheduling {
_app: any
_db: {|