UNPKG

@sap/cds

Version:

SAP Cloud Application Programming Model - CDS for Node.js

96 lines (86 loc) 2.79 kB
const PROCESSING = 'processing' const LOCKED = 'locked' const QUEUED = 'queued' const PLANNED = 'planned' const CALLBACKS = 'callbacks' module.exports = class TaskRunner { constructor() { this.states = new Map() } _setStateProp(prop, state, { name, tenant }) { const statesSrv = this.states.get(name) if (!statesSrv) { const newStatesSrv = new Map() newStatesSrv.set(tenant, { [prop]: state }) this.states.set(name, newStatesSrv) return state } const obj = statesSrv.get(tenant) if (!obj) { statesSrv.set(tenant, { [prop]: state }) return state } obj[prop] = state return state } _getStateProp(prop, { name, tenant }) { const statesSrv = this.states.get(name) if (!statesSrv) return const obj = statesSrv.get(tenant) return obj && obj[prop] } run({ name, tenant }, cb) { const processingState = this._getStateProp(PROCESSING, { name, tenant }) if (processingState === LOCKED) { this._setStateProp(PROCESSING, QUEUED, { name, tenant }) return } if (processingState === QUEUED) return if (!processingState) this._setStateProp(PROCESSING, LOCKED, { name, tenant }) return cb() } // Allows to plan, the shortest time wins plan({ name, tenant, waitingTime }, cb) { const newDate = Date.now() + waitingTime const alreadyPlanned = this._getStateProp(PLANNED, { name, tenant }) if (!alreadyPlanned || alreadyPlanned.date > newDate) { if (alreadyPlanned) clearInterval(alreadyPlanned.timer) this._setStateProp( PLANNED, { date: newDate, timer: setTimeout(() => (this._setStateProp(PLANNED, undefined, { name, tenant }), cb()), waitingTime) }, { name, tenant } ) } } end({ name, tenant }, cb) { const processingState = this._getStateProp(PROCESSING, { name, tenant }) this._setStateProp(PROCESSING, undefined, { name, tenant }) if (processingState === QUEUED) { cb() } else { // Truly done - call all done callbacks const callbacks = this.clearCallbacks({ name, tenant }) if (callbacks) { callbacks.forEach(callback => callback()) } } } getCallbacks({ name, tenant }) { return this._getStateProp(CALLBACKS, { name, tenant }) } addCallback({ name, tenant }, callback) { const existing = this._getStateProp(CALLBACKS, { name, tenant }) || [] if (!existing.includes(callback)) { existing.push(callback) this._setStateProp(CALLBACKS, existing, { name, tenant }) } } clearCallbacks({ name, tenant }) { const callbacks = this._getStateProp(CALLBACKS, { name, tenant }) this._setStateProp(CALLBACKS, undefined, { name, tenant }) return callbacks } }