UNPKG

@sap/cds

Version:

SAP Cloud Application Programming Model - CDS for Node.js

39 lines (37 loc) 1.81 kB
const { EventEmitter } = require('events') const EventContext = require('./context') module.exports = function spawn (o, fn, /** @type {import('../index')} */ cds=this) { if (typeof o === 'function') [fn,o] = [o,fn] //> for compatibility if (o instanceof EventContext) throw cds.error `The passed options must not be an instance of cds.EventContext.` const fx = ()=>{ const tx = cds.tx({...o}) // create a new detached transaction for each run of the background job return cds._with (tx, async ()=> { // REVISIT: The model must be set _after_ run to make sure that cds.context.tenant is correctly set. // Otherwise, `model4` could query the wrong database to check for extensions. if (cds.model && (cds.env.requires.extensibility || cds.env.requires.toggles)) { const ctx = cds.context const ExtendedModels = require('../srv/srv-models') // the sentinel is automatically started when required cds.context.model = await ExtendedModels.model4(ctx.tenant, ctx.features) tx.model = cds.context.model } return Promise.resolve(fn(tx)) .then (tx.commit, e => { cds.log().error(`ERROR occurred in background job:`, e) return tx.rollback(e) }) .then (res => Promise.all(em.listeners('succeeded').map(each => each(res)))) .catch (err => Promise.all(em.listeners('failed').map(each => each(err)))) .finally (() => Promise.all(em.listeners('done').map(each => each()))) }) } const em = new EventEmitter em.timer = ( o?.every ? setInterval(fx, o.every) : o?.after ? setTimeout(fx, o.after) : setImmediate(fx) ).unref() if (cds.env.server.shutdown_on_uncaught_errors) em.on ('failed', e => { if (cds.error.isSystemError(e)) cds.shutdown(e) }) return em }