@sap/cds 8.6.2 → 8.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/_i18n/i18n_en_US_saptrc.properties +4 -7
- package/bin/serve.js +3 -1
- package/lib/compile/for/lean_drafts.js +1 -1
- package/lib/compile/for/nodejs.js +1 -0
- package/lib/compile/to/sql.js +12 -8
- package/lib/core/classes.js +3 -4
- package/lib/core/types.js +1 -0
- package/lib/env/cds-env.js +2 -2
- package/lib/env/cds-requires.js +2 -2
- package/lib/ql/cds-ql.js +8 -1
- package/lib/ql/cds.ql-Query.js +9 -2
- package/lib/req/validate.js +1 -2
- package/lib/srv/cds-connect.js +2 -2
- package/lib/srv/cds-serve.js +2 -9
- package/lib/srv/cds.Service.js +0 -1
- package/lib/srv/factory.js +59 -71
- package/lib/srv/middlewares/auth/ias-auth.js +44 -14
- package/lib/srv/middlewares/auth/jwt-auth.js +45 -16
- package/lib/srv/middlewares/auth/xssec.js +1 -1
- package/lib/srv/middlewares/errors.js +8 -10
- package/lib/utils/cds-utils.js +5 -1
- package/lib/utils/tar-lib.js +58 -0
- package/libx/_runtime/common/Service.js +0 -4
- package/libx/_runtime/common/generic/input.js +1 -1
- package/libx/_runtime/common/utils/csn.js +5 -1
- package/libx/_runtime/fiori/lean-draft.js +6 -5
- package/libx/_runtime/messaging/enterprise-messaging-shared.js +7 -3
- package/libx/common/utils/path.js +2 -0
- package/libx/odata/middleware/create.js +7 -3
- package/libx/odata/middleware/delete.js +2 -0
- package/libx/odata/middleware/operation.js +2 -0
- package/libx/odata/middleware/read.js +4 -0
- package/libx/odata/middleware/stream.js +4 -0
- package/libx/odata/middleware/update.js +4 -0
- package/libx/odata/parse/afterburner.js +2 -2
- package/libx/odata/parse/multipartToJson.js +0 -1
- package/libx/odata/utils/normalizeTimeData.js +43 -0
- package/libx/odata/utils/readAfterWrite.js +1 -1
- package/libx/outbox/index.js +1 -1
- package/libx/rest/RestAdapter.js +2 -2
- package/package.json +6 -2
- package/lib/srv/protocols/odata-v2.js +0 -26
- package/libx/_runtime/common/code-ext/WorkerPool.js +0 -90
- package/libx/_runtime/common/code-ext/WorkerReq.js +0 -77
- package/libx/_runtime/common/code-ext/config.js +0 -13
- package/libx/_runtime/common/code-ext/execute.js +0 -123
- package/libx/_runtime/common/code-ext/handlers.js +0 -50
- package/libx/_runtime/common/code-ext/worker.js +0 -70
- package/libx/_runtime/common/code-ext/workerQueryExecutor.js +0 -37
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
const cds = require('../../cds')
|
|
2
|
-
const os = require('os')
|
|
3
|
-
const { Worker } = require('worker_threads')
|
|
4
|
-
|
|
5
|
-
class ExtensionWorker extends Worker {
|
|
6
|
-
constructor(id, workerPath, options) {
|
|
7
|
-
super(workerPath, options)
|
|
8
|
-
this.id = id
|
|
9
|
-
this.tasksAssigned = 0
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
class WorkerPool {
|
|
14
|
-
static instances = []
|
|
15
|
-
constructor(workerPath, options) {
|
|
16
|
-
this.workerPath = workerPath
|
|
17
|
-
this.options = options
|
|
18
|
-
this.size = options.size ?? Math.max(os.cpus().length, 1)
|
|
19
|
-
this.idleWorkers = new Set()
|
|
20
|
-
this.workers = []
|
|
21
|
-
WorkerPool.instances.push(this)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
#createWorker() {
|
|
25
|
-
const id = cds.utils.uuid()
|
|
26
|
-
const worker = new ExtensionWorker(id, this.workerPath, {
|
|
27
|
-
workerData: { id },
|
|
28
|
-
resourceLimits: this.options.resourceLimits
|
|
29
|
-
})
|
|
30
|
-
worker.on('exit', this.#onWorkerExit.bind(this, worker))
|
|
31
|
-
return worker
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
#onWorkerExit(worker) {
|
|
35
|
-
this.idleWorkers.delete(worker)
|
|
36
|
-
this.workers.splice(this.workers.indexOf(worker), 1)
|
|
37
|
-
worker.tasksAssigned = 0
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
adquire() {
|
|
41
|
-
if (this.idleWorkers.size === 0 && this.workers.length < this.size) {
|
|
42
|
-
const worker = this.#createWorker()
|
|
43
|
-
this.idleWorkers.add(worker)
|
|
44
|
-
this.workers.push(worker)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const worker = this.idleWorkers.values().next().value
|
|
48
|
-
|
|
49
|
-
if (worker) {
|
|
50
|
-
this.idleWorkers.delete(worker)
|
|
51
|
-
worker.tasksAssigned++
|
|
52
|
-
return worker
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const randomWorkerIndex = Math.floor(Math.random() * this.workers.length)
|
|
56
|
-
const busyWorker = this.workers[randomWorkerIndex]
|
|
57
|
-
busyWorker.tasksAssigned++
|
|
58
|
-
return busyWorker
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
release(worker) {
|
|
62
|
-
if (worker.tasksAssigned === 0) return
|
|
63
|
-
|
|
64
|
-
worker.tasksAssigned--
|
|
65
|
-
if (worker.tasksAssigned === 0) {
|
|
66
|
-
this.idleWorkers.add(worker)
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async destroy() {
|
|
71
|
-
if (this.workers.length === 0) return
|
|
72
|
-
|
|
73
|
-
const workers = Array.from(this.workers)
|
|
74
|
-
const iterable = workers.map(worker => {
|
|
75
|
-
worker.removeAllListeners()
|
|
76
|
-
return worker.terminate()
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
await Promise.all(iterable)
|
|
80
|
-
this.idleWorkers = new Set()
|
|
81
|
-
this.workers = []
|
|
82
|
-
WorkerPool.instances = []
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
static async destroyAll() {
|
|
86
|
-
for (const workerPool of WorkerPool.instances) await workerPool.destroy()
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
module.exports = WorkerPool
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
const { parentPort } = require('worker_threads')
|
|
2
|
-
const { Responses, Errors } = require('../../../../lib/req/response')
|
|
3
|
-
|
|
4
|
-
class WorkerReq {
|
|
5
|
-
constructor(contextId, reqData) {
|
|
6
|
-
this.contextId = contextId
|
|
7
|
-
Object.assign(this, reqData)
|
|
8
|
-
this.postMessages = []
|
|
9
|
-
this.messages = this.messages ?? []
|
|
10
|
-
this.errors = this.errors ?? new Errors()
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
#push(args) {
|
|
14
|
-
this.postMessages.push({
|
|
15
|
-
kind: 'run',
|
|
16
|
-
target: 'req',
|
|
17
|
-
...args
|
|
18
|
-
})
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
notify(...args) {
|
|
22
|
-
this.#push({
|
|
23
|
-
prop: 'notify',
|
|
24
|
-
args
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
const notify = Responses.get(1, ...args)
|
|
28
|
-
this.messages.push(notify)
|
|
29
|
-
return notify
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
info(...args) {
|
|
33
|
-
this.#push({
|
|
34
|
-
prop: 'info',
|
|
35
|
-
args
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
const info = Responses.get(2, ...args)
|
|
39
|
-
this.messages.push(info)
|
|
40
|
-
return info
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
warn(...args) {
|
|
44
|
-
this.#push({
|
|
45
|
-
prop: 'warn',
|
|
46
|
-
args
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
const warn = Responses.get(3, ...args)
|
|
50
|
-
this.messages.push(warn)
|
|
51
|
-
return warn
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
error(...args) {
|
|
55
|
-
this.#push({
|
|
56
|
-
prop: 'error',
|
|
57
|
-
args
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
let error = Responses.get(4, ...args)
|
|
61
|
-
if (!error.stack) Error.captureStackTrace((error = Object.assign(new Error(), error)), this.error)
|
|
62
|
-
this.errors.push(error)
|
|
63
|
-
return error
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
reject(...args) {
|
|
67
|
-
parentPort.postMessage({
|
|
68
|
-
contextId: this.contextId,
|
|
69
|
-
kind: 'run',
|
|
70
|
-
target: 'req',
|
|
71
|
-
prop: 'reject',
|
|
72
|
-
args
|
|
73
|
-
})
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
module.exports = WorkerReq
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
const os = require('os')
|
|
2
|
-
const totalMemory = os.totalmem() // total amount of system memory in bytes
|
|
3
|
-
const maxOldGenerationSizeMb = Math.floor(totalMemory / 1024 ** 2 / 8) // max size of the main heap in MB
|
|
4
|
-
const maxYoungGenerationSizeMb = Math.floor(totalMemory / 1024 ** 2 / 8) // max size of a heap space for recently created objects
|
|
5
|
-
|
|
6
|
-
module.exports = {
|
|
7
|
-
timeout: 10000,
|
|
8
|
-
resourceLimits: {
|
|
9
|
-
maxOldGenerationSizeMb,
|
|
10
|
-
maxYoungGenerationSizeMb,
|
|
11
|
-
stackSizeMb: 4 // default
|
|
12
|
-
}
|
|
13
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
const cds = require('../../cds')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const { AsyncResource } = require('async_hooks')
|
|
4
|
-
const { timeout, resourceLimits } = require('./config')
|
|
5
|
-
const WorkerPool = require('./WorkerPool')
|
|
6
|
-
const workerPath = path.resolve(__dirname, 'worker.js')
|
|
7
|
-
const workerPool = new WorkerPool(workerPath, { resourceLimits })
|
|
8
|
-
const { Errors } = require('../../../../lib/req/response')
|
|
9
|
-
const LOG = cds.log()
|
|
10
|
-
const _getReqData = req => {
|
|
11
|
-
return {
|
|
12
|
-
data: req.data,
|
|
13
|
-
params: req.params,
|
|
14
|
-
results: req.results,
|
|
15
|
-
messages: req.messages,
|
|
16
|
-
errors: req.errors ?? new Errors()
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
module.exports = async function executeCode(code, req) {
|
|
21
|
-
const reqData = _getReqData(req)
|
|
22
|
-
const srv = this
|
|
23
|
-
const _getTarget = target => {
|
|
24
|
-
switch (target) {
|
|
25
|
-
case 'srv':
|
|
26
|
-
return srv
|
|
27
|
-
|
|
28
|
-
case 'req':
|
|
29
|
-
return req
|
|
30
|
-
|
|
31
|
-
// no default
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const worker = workerPool.adquire()
|
|
36
|
-
const workerId = worker.id
|
|
37
|
-
const contextId = cds.utils.uuid()
|
|
38
|
-
const executePromise = new Promise(function executeCodePromiseExecutor(resolve, reject) {
|
|
39
|
-
queueMicrotask(AsyncResource.bind(onStarted)) // eslint-disable-line no-undef
|
|
40
|
-
const onMessageReceivedProxy = AsyncResource.bind(onMessageReceived)
|
|
41
|
-
const onErrorProxy = AsyncResource.bind(onError)
|
|
42
|
-
const onExitProxy = AsyncResource.bind(onExit)
|
|
43
|
-
worker.on('message', onMessageReceivedProxy)
|
|
44
|
-
worker.on('error', onErrorProxy)
|
|
45
|
-
worker.on('exit', onExitProxy)
|
|
46
|
-
|
|
47
|
-
let onStartTimeoutID
|
|
48
|
-
function onStarted() {
|
|
49
|
-
onStartTimeoutID = setTimeout(() => {
|
|
50
|
-
worker.terminate()
|
|
51
|
-
reject(new Error(`Script execution timed out after ${timeout}ms`))
|
|
52
|
-
}, timeout)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function onMessageReceived(message) {
|
|
56
|
-
if (message.contextId !== contextId) return
|
|
57
|
-
|
|
58
|
-
if (LOG._debug)
|
|
59
|
-
LOG.debug(`Post message received on main thread (code-ext/execute.js) from worker thread`, message)
|
|
60
|
-
|
|
61
|
-
switch (message.kind) {
|
|
62
|
-
case 'run':
|
|
63
|
-
run(message)
|
|
64
|
-
return
|
|
65
|
-
|
|
66
|
-
case 'success':
|
|
67
|
-
onSuccess(message)
|
|
68
|
-
return
|
|
69
|
-
|
|
70
|
-
case 'error':
|
|
71
|
-
onError(message.error)
|
|
72
|
-
return
|
|
73
|
-
|
|
74
|
-
// no default
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async function onSuccess(message) {
|
|
79
|
-
for (const m of message.postMessages) await run(m)
|
|
80
|
-
req.data && Object.assign(req.data, message.req.data) // REVISIT: Why Object.assign(...) is a required?
|
|
81
|
-
req.results = message.req.results
|
|
82
|
-
cleanup()
|
|
83
|
-
resolve(req.results ?? message.result)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function onError(error) {
|
|
87
|
-
cleanup()
|
|
88
|
-
reject(error)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function onExit(exitCode) {
|
|
92
|
-
if (exitCode !== 0) {
|
|
93
|
-
reject(new Error(`Worker thread stopped with exit code ${exitCode}`))
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
async function run(message) {
|
|
98
|
-
try {
|
|
99
|
-
let result = _getTarget(message.target)[message.prop](...message.args)
|
|
100
|
-
if (typeof result?.then === 'function') result = await result
|
|
101
|
-
if (message.responseData) worker.postMessage({ id: message.id, kind: 'responseData', result })
|
|
102
|
-
} catch (error) {
|
|
103
|
-
if (LOG._debug) LOG.debug(`Calling ${message.target}.${message.prop}(...) throws an error.`, error)
|
|
104
|
-
if (message.id) worker.postMessage({ id: message.id, kind: 'cleanup' })
|
|
105
|
-
cleanup()
|
|
106
|
-
reject(error)
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function cleanup() {
|
|
111
|
-
clearTimeout(onStartTimeoutID)
|
|
112
|
-
worker.removeListener('message', onMessageReceivedProxy)
|
|
113
|
-
worker.removeListener('error', onErrorProxy)
|
|
114
|
-
worker.removeListener('exit', onExitProxy)
|
|
115
|
-
workerPool.release(worker)
|
|
116
|
-
}
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
// triggers execution of the code in the worker thread
|
|
120
|
-
const message = { contextId, workerId, kind: 'start', code, reqData }
|
|
121
|
-
worker.postMessage(message)
|
|
122
|
-
return executePromise
|
|
123
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
const cds = require('../../cds')
|
|
2
|
-
const LOG = cds.log()
|
|
3
|
-
const executeCode = require('./execute')
|
|
4
|
-
const CODE_ANNOTATION = '@extension.code'
|
|
5
|
-
|
|
6
|
-
module.exports = cds.service.impl(function () {
|
|
7
|
-
const getCodeFromAnnotation = async (defName, operation, registration) => {
|
|
8
|
-
// REVISIT: tenant info in not in this.model and cds.context.model is undefined for single tenancy
|
|
9
|
-
const model = cds.context.model || this.model
|
|
10
|
-
const el = model.definitions[defName]
|
|
11
|
-
const boundEl = el.actions?.[operation]
|
|
12
|
-
const extensionCode = boundEl?.[CODE_ANNOTATION] ?? el[CODE_ANNOTATION]
|
|
13
|
-
if (extensionCode) {
|
|
14
|
-
const annotation = extensionCode.filter(element => element[registration] === operation)
|
|
15
|
-
return annotation.length && annotation[0].code
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
this.after('READ', async function (result, req) {
|
|
20
|
-
if (result == null) return // whether result is null or undefined
|
|
21
|
-
const code = await getCodeFromAnnotation(req.target.name, req.event, 'after')
|
|
22
|
-
if (!code) return
|
|
23
|
-
await executeCode.call(this, code, req).catch(error => LOG._debug && LOG.debug(error))
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
this.before(['CREATE', 'UPDATE', 'DELETE'], async function (req) {
|
|
27
|
-
const code = await getCodeFromAnnotation(req.target.name, req.event, 'before')
|
|
28
|
-
if (!code) return
|
|
29
|
-
await executeCode.call(this, code, req).catch(error => LOG._debug && LOG.debug(error))
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
this.on('*', async function (req, next) {
|
|
33
|
-
if (this.name.startsWith('cds.xt')) return next()
|
|
34
|
-
|
|
35
|
-
// REVISIT: req.target -> wait until implementation task finished
|
|
36
|
-
let fqn = req.target?.actions?.[`${req.event}`] // check for bound action/function
|
|
37
|
-
if (!fqn) {
|
|
38
|
-
if (req.target) return next()
|
|
39
|
-
fqn = this.model.definitions[`${this.name}.${req.event}`] // check for bound action/function or event
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// REVISIT: DO NOT OVERWRITE EXISTING Action Implementations!
|
|
43
|
-
// REVISIT: check whether action/function or event is part of an extension
|
|
44
|
-
if (fqn.kind === 'action' || fqn.kind === 'function' || req.constructor.name === 'EventMessage') {
|
|
45
|
-
const code = await getCodeFromAnnotation(req?.target?.name ?? fqn.name, req.event, 'on')
|
|
46
|
-
if (!code) return next()
|
|
47
|
-
return await executeCode.call(this, code, req).catch(error => LOG._debug && LOG.debug(error))
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
})
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
const cds = require('../../cds')
|
|
2
|
-
const LOG = cds.log()
|
|
3
|
-
const { parentPort, workerData } = require('worker_threads')
|
|
4
|
-
const queryExecutor = require('./workerQueryExecutor')
|
|
5
|
-
const WorkerReq = require('./WorkerReq')
|
|
6
|
-
const { timeout } = require('./config')
|
|
7
|
-
|
|
8
|
-
parentPort.on('message', function onWorkerMessageReceived(message) {
|
|
9
|
-
const { contextId, workerId, kind, code, reqData } = message
|
|
10
|
-
if (kind !== 'start' || workerId !== workerData.id) return
|
|
11
|
-
if (LOG._debug) LOG.debug(`Post message received on worker thread (worker.js) from main thread`, message)
|
|
12
|
-
|
|
13
|
-
const { VM } = require('vm2')
|
|
14
|
-
const workerReq = new WorkerReq(contextId, reqData)
|
|
15
|
-
|
|
16
|
-
class WorkerSELECT extends SELECT.class {
|
|
17
|
-
then(r, e) {
|
|
18
|
-
return new Promise(queryExecutor.bind(this, contextId)).then(r, e)
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
class WorkerINSERT extends INSERT.class {
|
|
23
|
-
then(r, e) {
|
|
24
|
-
return new Promise(queryExecutor.bind(this, contextId)).then(r, e)
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
class WorkerUPSERT extends UPSERT.class {
|
|
29
|
-
then(r, e) {
|
|
30
|
-
return new Promise(queryExecutor.bind(this, contextId)).then(r, e)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
class WorkerUPDATE extends UPDATE.class {
|
|
35
|
-
then(r, e) {
|
|
36
|
-
return new Promise(queryExecutor.bind(this, contextId)).then(r, e)
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
class WorkerDELETE extends DELETE.class {
|
|
41
|
-
then(r, e) {
|
|
42
|
-
return new Promise(queryExecutor.bind(this, contextId)).then(r, e)
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const vm = new VM({
|
|
47
|
-
console: 'inherit',
|
|
48
|
-
timeout, // specifies the number of milliseconds to execute code before terminating execution
|
|
49
|
-
allowAsync: true,
|
|
50
|
-
|
|
51
|
-
// the sandbox represents the global object inside the vm instance
|
|
52
|
-
sandbox: {
|
|
53
|
-
req: workerReq,
|
|
54
|
-
SELECT: WorkerSELECT._api(),
|
|
55
|
-
INSERT: WorkerINSERT._api(),
|
|
56
|
-
UPSERT: WorkerUPSERT._api(),
|
|
57
|
-
UPDATE: WorkerUPDATE._api(),
|
|
58
|
-
DELETE: WorkerDELETE._api()
|
|
59
|
-
}
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
try {
|
|
63
|
-
;(async function () {
|
|
64
|
-
const result = await vm.run(code)
|
|
65
|
-
parentPort.postMessage({ contextId, kind: 'success', req: reqData, postMessages: workerReq.postMessages, result })
|
|
66
|
-
})()
|
|
67
|
-
} catch (error) {
|
|
68
|
-
parentPort.postMessage({ contextId, kind: 'error', error })
|
|
69
|
-
}
|
|
70
|
-
})
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
const cds = require('../../cds')
|
|
2
|
-
const LOG = cds.log()
|
|
3
|
-
const { parentPort } = require('worker_threads')
|
|
4
|
-
const executionContextMap = new Map()
|
|
5
|
-
|
|
6
|
-
parentPort.on('message', function onWorkerMessageReceived(message) {
|
|
7
|
-
const { id, kind, result } = message
|
|
8
|
-
if (!executionContextMap.has(id)) return
|
|
9
|
-
if (LOG._debug) LOG.debug(`Post message received on worker thread (workerQueryExecutor.js) from main thread`, message)
|
|
10
|
-
|
|
11
|
-
switch (kind) {
|
|
12
|
-
case 'responseData':
|
|
13
|
-
executionContextMap.get(id)(result)
|
|
14
|
-
executionContextMap.delete(id)
|
|
15
|
-
return
|
|
16
|
-
|
|
17
|
-
case 'cleanup':
|
|
18
|
-
executionContextMap.delete(id)
|
|
19
|
-
return
|
|
20
|
-
}
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
function queryExecutor(contextId, resolve) {
|
|
24
|
-
const id = cds.utils.uuid()
|
|
25
|
-
executionContextMap.set(id, result => resolve(result))
|
|
26
|
-
parentPort.postMessage({
|
|
27
|
-
id,
|
|
28
|
-
contextId,
|
|
29
|
-
kind: 'run',
|
|
30
|
-
target: 'srv',
|
|
31
|
-
prop: 'run',
|
|
32
|
-
responseData: true,
|
|
33
|
-
args: [this]
|
|
34
|
-
})
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
module.exports = queryExecutor
|