@live-change/framework 0.9.171 → 0.9.174
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/lib/App.js +327 -239
- package/lib/processes/commandExecutor.js +126 -56
- package/lib/processes/eventListener.js +32 -7
- package/lib/processes/triggerExecutor.js +28 -1
- package/lib/runtime/Action.js +63 -34
- package/lib/runtime/EventHandler.js +7 -1
- package/lib/runtime/TriggerHandler.js +130 -55
- package/lib/utils.js +59 -0
- package/package.json +4 -4
- package/tsconfig.json +3 -2
|
@@ -2,6 +2,21 @@ import { prepareParameters, processReturn } from "./params.js"
|
|
|
2
2
|
import SplitEmitQueue from "../utils/SplitEmitQueue.js"
|
|
3
3
|
import SingleEmitQueue from "../utils/SingleEmitQueue.js"
|
|
4
4
|
|
|
5
|
+
import { context, propagation, trace } from '@opentelemetry/api'
|
|
6
|
+
import { SpanKind } from '@opentelemetry/api'
|
|
7
|
+
const tracer = trace.getTracer('live-change:triggerHandler')
|
|
8
|
+
|
|
9
|
+
import { expandObjectAttributes } from '../utils.js'
|
|
10
|
+
|
|
11
|
+
async function spanAttributes(trig, service) {
|
|
12
|
+
return {
|
|
13
|
+
...expandObjectAttributes(trig, 'trigger'),
|
|
14
|
+
service: service.name
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
import { loggingHelpers } from '../utils.js'
|
|
19
|
+
|
|
5
20
|
class TriggerHandler {
|
|
6
21
|
|
|
7
22
|
constructor(definition, service) {
|
|
@@ -14,6 +29,10 @@ class TriggerHandler {
|
|
|
14
29
|
Array.isArray(queuedBy) ? (c) => JSON.stringify(queuedBy.map(k=>c[k])) :
|
|
15
30
|
(c) => JSON.stringify(c[queuedBy]) )
|
|
16
31
|
}
|
|
32
|
+
|
|
33
|
+
this.loggingHelpers = loggingHelpers(service.name, service.app.config.clientConfig.version, {
|
|
34
|
+
triggerType: definition.name,
|
|
35
|
+
})
|
|
17
36
|
}
|
|
18
37
|
|
|
19
38
|
async doExecute(trig, emit) {
|
|
@@ -42,7 +61,8 @@ class TriggerHandler {
|
|
|
42
61
|
cause: trig.id,
|
|
43
62
|
client: trig.client,
|
|
44
63
|
...trigger
|
|
45
|
-
}, data, returnArray)
|
|
64
|
+
}, data, returnArray),
|
|
65
|
+
...this.loggingHelpers
|
|
46
66
|
}, emit))
|
|
47
67
|
//console.log("RESULT PROMISE", resultPromise, resultPromise.then)
|
|
48
68
|
resultPromise = resultPromise.then(async result => {
|
|
@@ -50,75 +70,130 @@ class TriggerHandler {
|
|
|
50
70
|
return processedResult
|
|
51
71
|
})
|
|
52
72
|
resultPromise.catch(error => {
|
|
53
|
-
|
|
73
|
+
this.loggingHelpers.error(`Trigger ${this.definition.name} error `, error)
|
|
54
74
|
})
|
|
55
75
|
return resultPromise
|
|
56
76
|
}
|
|
57
77
|
|
|
58
78
|
async execute(trig, service) {
|
|
59
|
-
console.log("EXECUTE", trig, this.queueKeyFunction)
|
|
79
|
+
//console.log("EXECUTE", trig, this.queueKeyFunction)
|
|
60
80
|
const profileOp = await service.profileLog.begin({
|
|
61
81
|
operation: 'queueTrigger', triggerType: this.definition.name,
|
|
62
82
|
triggerId: trig.id, by: trig.by
|
|
63
83
|
})
|
|
64
84
|
if(this.queueKeyFunction) {
|
|
65
|
-
console.log("QUEUED TRIGGER STARTED", trig)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}, async () => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
85
|
+
//console.log("QUEUED TRIGGER STARTED", trig)
|
|
86
|
+
return tracer.startActiveSpan('queueTrigger:'+service.name+'.'+this.definition.name, {
|
|
87
|
+
kind: SpanKind.INTERNAL,
|
|
88
|
+
attributes: spanAttributes(trig, service)
|
|
89
|
+
}, async (queueSpan) => {
|
|
90
|
+
const queueContext = context.active()
|
|
91
|
+
|
|
92
|
+
const routine = () => service.profileLog.profile({
|
|
93
|
+
operation: 'runTrigger', triggerType: this.definition.name,
|
|
94
|
+
commandId: trig.id, by: trig.by
|
|
95
|
+
}, async () => {
|
|
96
|
+
return tracer.startActiveSpan('handleTrigger:'+service.name+'.'+this.definition.name, {
|
|
97
|
+
kind: SpanKind.INTERNAL,
|
|
98
|
+
attributes: spanAttributes(trig, service)
|
|
99
|
+
}, queueContext, async (handleSpan) => {
|
|
100
|
+
let result
|
|
101
|
+
const reportFinished = this.definition.waitForEvents ? 'trigger_' + trig.id : undefined
|
|
102
|
+
const _trace = {}
|
|
103
|
+
propagation.inject(context.active(), _trace)
|
|
104
|
+
const flags = {triggerId: trig.id, reportFinished, _trace }
|
|
105
|
+
const emit = service.app.splitEvents
|
|
106
|
+
? new SplitEmitQueue(service, flags)
|
|
107
|
+
: new SingleEmitQueue(service, flags)
|
|
108
|
+
|
|
109
|
+
await tracer.startActiveSpan('runTrigger', {
|
|
110
|
+
kind: SpanKind.SERVER,
|
|
111
|
+
attributes: spanAttributes(trig, service)
|
|
112
|
+
}, queueContext, async (runSpan) => {
|
|
113
|
+
try {
|
|
114
|
+
//console.log("TRIGGER RUNNING!", trig)
|
|
115
|
+
|
|
116
|
+
result = await service.app.assertTime('trigger ' + this.definition.name,
|
|
117
|
+
this.definition.timeout || 10000,
|
|
118
|
+
() => this.doExecute(trig, (...args) => emit.emit(...args)))
|
|
119
|
+
} catch (e) {
|
|
120
|
+
this.loggingHelpers.error(`Trigger ${this.definition.name} error `, e.stack)
|
|
121
|
+
runSpan.end()
|
|
122
|
+
handleSpan.end()
|
|
123
|
+
queueSpan.end()
|
|
124
|
+
throw e
|
|
125
|
+
}
|
|
126
|
+
runSpan.end()
|
|
127
|
+
return result
|
|
128
|
+
})
|
|
129
|
+
return await tracer.startActiveSpan('emitEvents', {
|
|
130
|
+
kind: SpanKind.INTERNAL,
|
|
131
|
+
attributes: spanAttributes(trig, service)
|
|
132
|
+
}, queueContext, async (emitEventsSpan) => {
|
|
133
|
+
const events = await emit.commit()
|
|
134
|
+
if (this.definition.waitForEvents)
|
|
135
|
+
await service.app.waitForEvents(reportFinished, events, this.definition.waitForEvents)
|
|
136
|
+
emitEventsSpan.end()
|
|
137
|
+
handleSpan.end()
|
|
138
|
+
queueSpan.end()
|
|
139
|
+
return result
|
|
140
|
+
})
|
|
141
|
+
})
|
|
142
|
+
})
|
|
76
143
|
try {
|
|
77
|
-
|
|
78
|
-
result = await service.app.assertTime('trigger ' + this.definition.name,
|
|
79
|
-
this.definition.timeout || 10000,
|
|
80
|
-
() => this.doExecute(trig, (...args) => emit.emit(...args)))
|
|
81
|
-
console.log("TRIGGER DONE!", trig)
|
|
144
|
+
routine.key = this.queueKeyFunction(trig)
|
|
82
145
|
} catch (e) {
|
|
83
|
-
|
|
84
|
-
throw e
|
|
146
|
+
this.loggingHelpers.error("Queue key function error ", e)
|
|
85
147
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return
|
|
148
|
+
this.loggingHelpers.log("Trigger queue key", routine.key)
|
|
149
|
+
const promise = service.keyBasedExecutionQueues.queue(routine)
|
|
150
|
+
await service.profileLog.endPromise(profileOp, promise)
|
|
151
|
+
return promise
|
|
90
152
|
})
|
|
91
|
-
try {
|
|
92
|
-
routine.key = this.queueKeyFunction(trig)
|
|
93
|
-
} catch (e) {
|
|
94
|
-
console.error("QUEUE KEY FUNCTION ERROR", e)
|
|
95
|
-
}
|
|
96
|
-
console.log("TRIGGER QUEUE KEY", routine.key)
|
|
97
|
-
const promise = service.keyBasedExecutionQueues.queue(routine)
|
|
98
|
-
await service.profileLog.endPromise(profileOp, promise)
|
|
99
|
-
return promise
|
|
100
153
|
} else {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
154
|
+
return tracer.startActiveSpan('handleTrigger:'+service.name+'.'+this.definition.name, {
|
|
155
|
+
kind: SpanKind.INTERNAL,
|
|
156
|
+
attributes: spanAttributes(trig, service)
|
|
157
|
+
}, async (handleSpan) => {
|
|
158
|
+
this.loggingHelpers.log("Not queued trigger started", trig)
|
|
159
|
+
const reportFinished = this.definition.waitForEvents ? 'trigger_'+trig.id : undefined
|
|
160
|
+
const _trace = {}
|
|
161
|
+
propagation.inject(context.active(), _trace)
|
|
162
|
+
const flags = { triggerId: trig.id, reportFinished, _trace }
|
|
163
|
+
const emit = service.app.splitEvents
|
|
164
|
+
? new SplitEmitQueue(service, flags)
|
|
165
|
+
: new SingleEmitQueue(service, flags)
|
|
166
|
+
let result
|
|
167
|
+
await tracer.startActiveSpan('runTrigger:'+service.name+'.'+this.definition.name, {
|
|
168
|
+
kind: SpanKind.SERVER,
|
|
169
|
+
attributes: spanAttributes(trig, service)
|
|
170
|
+
}, async (runSpan) => {
|
|
171
|
+
try {
|
|
172
|
+
result = await service.app.assertTime('trigger '+this.definition.name,
|
|
173
|
+
this.definition.timeout || 10000,
|
|
174
|
+
() => this.doExecute(trig, (...args) => emit.emit(...args)))
|
|
175
|
+
runSpan.end()
|
|
176
|
+
this.loggingHelpers.log("Trigger done", trig)
|
|
177
|
+
} catch (e) {
|
|
178
|
+
this.loggingHelpers.error(`Trigger ${this.definition.name} error `, e.stack)
|
|
179
|
+
runSpan.end()
|
|
180
|
+
handleSpan.end()
|
|
181
|
+
throw e
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
return tracer.startActiveSpan('emitEvents', {
|
|
185
|
+
kind: SpanKind.INTERNAL,
|
|
186
|
+
attributes: spanAttributes(trig, service)
|
|
187
|
+
}, async (emitEventsSpan) => {
|
|
188
|
+
const events = await emit.commit()
|
|
189
|
+
if(this.definition.waitForEvents)
|
|
190
|
+
await service.app.waitForEvents(reportFinished, events, this.definition.waitForEvents)
|
|
191
|
+
emitEventsSpan.end()
|
|
192
|
+
handleSpan.end()
|
|
193
|
+
await service.profileLog.end(profileOp)
|
|
194
|
+
return result
|
|
195
|
+
})
|
|
196
|
+
})
|
|
122
197
|
}
|
|
123
198
|
}
|
|
124
199
|
|
package/lib/utils.js
CHANGED
|
@@ -365,4 +365,63 @@ export function parseDuration(duration) {
|
|
|
365
365
|
result += value * { s: 1000, m: 60000, h: 3600000, d: 86400000 }[unit]
|
|
366
366
|
}
|
|
367
367
|
return result
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
import { logs, SeverityNumber } from '@opentelemetry/api-logs'
|
|
371
|
+
import { context } from '@opentelemetry/api'
|
|
372
|
+
|
|
373
|
+
export function loggingHelper(logger, severityNumber, severityText, attributes) {
|
|
374
|
+
return (message, ...args) => {
|
|
375
|
+
logger.emit({
|
|
376
|
+
severityNumber, severityText,
|
|
377
|
+
body: [message, ...args].map(a => {
|
|
378
|
+
try {
|
|
379
|
+
return JSON.stringify(a)
|
|
380
|
+
} catch (e) {
|
|
381
|
+
return `${a}`
|
|
382
|
+
}
|
|
383
|
+
}).join(' '),
|
|
384
|
+
attributes: {
|
|
385
|
+
...attributes,
|
|
386
|
+
'log.type': 'LogRecord',
|
|
387
|
+
message,
|
|
388
|
+
logArgs: args.map(a => {
|
|
389
|
+
try {
|
|
390
|
+
return JSON.stringify(a)
|
|
391
|
+
} catch (e) {
|
|
392
|
+
return `${a}`
|
|
393
|
+
}
|
|
394
|
+
}),
|
|
395
|
+
},
|
|
396
|
+
context: context.active()
|
|
397
|
+
})
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export function loggingHelpers(name, version, attributes, options) {
|
|
402
|
+
const logger = logs.getLogger(name, version, options)
|
|
403
|
+
return {
|
|
404
|
+
log: loggingHelper(logger, SeverityNumber.INFO, 'INFO', attributes),
|
|
405
|
+
warn: loggingHelper(logger, SeverityNumber.WARN, 'WARN', attributes),
|
|
406
|
+
error: loggingHelper(logger, SeverityNumber.ERROR, 'ERROR', attributes),
|
|
407
|
+
debug: loggingHelper(logger, SeverityNumber.DEBUG, 'DEBUG', attributes),
|
|
408
|
+
trace: loggingHelper(logger, SeverityNumber.TRACE, 'TRACE', attributes),
|
|
409
|
+
fatal: loggingHelper(logger, SeverityNumber.FATAL, 'FATAL', attributes),
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export function expandObjectAttributes(object, prefix = '', acc = {}) {
|
|
414
|
+
if(typeof object !== 'object') {
|
|
415
|
+
acc[prefix] = object
|
|
416
|
+
return
|
|
417
|
+
}
|
|
418
|
+
if(object === null || object === undefined) {
|
|
419
|
+
acc[prefix] = object
|
|
420
|
+
return
|
|
421
|
+
}
|
|
422
|
+
//if(Array.isArray(object)) return object.map(item => expandObjectAttributes(item, prefix))
|
|
423
|
+
for(const [key, value] of Object.entries(object)) {
|
|
424
|
+
expandObjectAttributes(value, prefix + '_' + key, acc)
|
|
425
|
+
}
|
|
426
|
+
return acc
|
|
368
427
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@live-change/framework",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.174",
|
|
4
4
|
"description": "Live Change Framework - ultimate solution for real time mobile/web apps",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
},
|
|
23
23
|
"homepage": "https://github.com/live-change/live-change-stack",
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@live-change/dao": "^0.9.
|
|
26
|
-
"@live-change/uid": "^0.9.
|
|
25
|
+
"@live-change/dao": "^0.9.174",
|
|
26
|
+
"@live-change/uid": "^0.9.174",
|
|
27
27
|
"typedoc": "0.28.3",
|
|
28
28
|
"typedoc-plugin-markdown": "^4.6.3",
|
|
29
29
|
"typedoc-plugin-rename-defaults": "^0.7.3"
|
|
30
30
|
},
|
|
31
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "6ebdadad702526df240bd3aa7ac3d97324a0308a"
|
|
32
32
|
}
|
package/tsconfig.json
CHANGED
|
@@ -20,11 +20,12 @@
|
|
|
20
20
|
"esModuleInterop": true, // Enable interop for ES modules
|
|
21
21
|
"resolveJsonModule": true, // Allow importing JSON files
|
|
22
22
|
"skipLibCheck": true,
|
|
23
|
-
"noImplicitAny": false
|
|
23
|
+
"noImplicitAny": false,
|
|
24
|
+
"types": []
|
|
24
25
|
},
|
|
25
26
|
"files": ["index.ts"],
|
|
26
27
|
"include": [
|
|
27
28
|
"lib/**/*.ts", "lib/**/*.js", "index.ts"],
|
|
28
|
-
"exclude": ["node_modules/@types", "node_modules/**/*.d.ts", "**/*.test.js", "**/CMakeFiles/**"]
|
|
29
|
+
"exclude": ["node_modules/@types", "node_modules/**/*.d.ts", "**/*.test.js", "**/CMakeFiles/**", "**/node_modules/@hapi/**"]
|
|
29
30
|
}
|
|
30
31
|
|