@sap/cds
Version:
SAP Cloud Application Programming Model - CDS for Node.js
81 lines (71 loc) • 2.29 kB
JavaScript
const PROCESSING = 'processing'
const LOCKED = 'locked'
const QUEUED = 'queued'
const CALLBACKS = 'callbacks'
module.exports = class JobExecutor {
constructor() {
statify(this)
}
run({ target, tenant, after }, cb) {
const exec = () => {
const processingState = this._get_state(PROCESSING, { target, tenant })
if (processingState === LOCKED) {
this._set_state(PROCESSING, QUEUED, { target, tenant })
return
}
if (processingState === QUEUED) return
if (!processingState) this._set_state(PROCESSING, LOCKED, { target, tenant })
return cb()
}
setTimeout(exec, after || 0).unref()
}
end({ target, tenant }, cb) {
const processingState = this._get_state(PROCESSING, { target, tenant })
this._set_state(PROCESSING, undefined, { target, tenant })
if (processingState === QUEUED) {
setTimeout(cb, 0).unref()
} else {
// Truly done - call all done callbacks
const callbacks = this._clearCallbacks({ target, tenant })
if (callbacks) callbacks.forEach(callback => callback())
}
}
addCallback({ target, tenant }, callback) {
const existing = this._get_state(CALLBACKS, { target, tenant }) || []
if (!existing.includes(callback)) {
existing.push(callback)
this._set_state(CALLBACKS, existing, { target, tenant })
}
}
_clearCallbacks({ target, tenant }) {
const callbacks = this._get_state(CALLBACKS, { target, tenant })
this._set_state(CALLBACKS, undefined, { target, tenant })
return callbacks
}
}
const statify = that => {
if (that._states) return
that._states = new Map()
that._set_state = (prop, state, { target, tenant }) => {
const statesSrv = that._states.get(target)
if (!statesSrv) {
const newStatesSrv = new Map()
newStatesSrv.set(tenant, { [prop]: state })
that._states.set(target, newStatesSrv)
return state
}
const obj = statesSrv.get(tenant)
if (!obj) {
statesSrv.set(tenant, { [prop]: state })
return state
}
obj[prop] = state
return state
}
that._get_state = (prop, { target, tenant }) => {
const statesSrv = that._states.get(target)
if (!statesSrv) return
const obj = statesSrv.get(tenant)
return obj && obj[prop]
}
}