chore(xo-server): handle nested job props (#2712)
This commit is contained in:
parent
e76a0ad4bd
commit
48b2297bc1
@ -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'
|
||||
|
@ -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
|
||||
}
|
||||
}
|
15
packages/xo-server/src/patch.js
Normal file
15
packages/xo-server/src/patch.js
Normal 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 }
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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: {|
|
||||
|
Loading…
Reference in New Issue
Block a user