@vida-global/core 2.0.5 → 2.0.7
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/activeRecord/baseRecord.js +17 -2
- package/lib/activeRecord/db/connection.js +42 -17
- package/lib/activeRecord/db/schema.js +47 -16
- package/lib/jobQueue/abstractJob.js +19 -4
- package/lib/jobQueue/queue.js +8 -4
- package/lib/jobQueue/worker.js +35 -20
- package/lib/logger/index.js +10 -6
- package/lib/logger/serverMiddleware.js +41 -26
- package/lib/server/server.js +25 -10
- package/lib/server/serverController.js +6 -1
- package/package.json +1 -1
- package/test/activeRecord/baseRecord.test.js +52 -10
- package/test/activeRecord/db/connection.test.js +16 -19
- package/test/activeRecord/db/queryInterface.test.js +1 -9
- package/test/activeRecord/db/schema.test.js +76 -58
- package/test/activeRecord/helpers/fixtures.js +10 -1
- package/test/activeRecord/helpers/queryInterface.js +14 -3
- package/test/jobQueue/abstractJob.test.js +15 -43
- package/test/jobQueue/helpers/abstractJob.js +14 -3
- package/test/jobQueue/helpers/queue.js +26 -0
- package/test/jobQueue/helpers/worker.js +13 -0
- package/test/jobQueue/queue.test.js +7 -26
- package/test/jobQueue/worker.test.js +28 -48
- package/test/logger/index.test.js +26 -0
- package/test/logger/serverMiddleware.test.js +6 -15
- package/test/server/helpers/server.js +40 -6
- package/test/server/server.test.js +6 -35
|
@@ -142,9 +142,19 @@ class BaseRecord extends Model {
|
|
|
142
142
|
/***********************************************************************************************
|
|
143
143
|
* DB CONNECTION
|
|
144
144
|
***********************************************************************************************/
|
|
145
|
+
static get connectionClass() {
|
|
146
|
+
return Connection;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
static buildConnection() {
|
|
151
|
+
return new this.connectionClass(this.databaseId);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
145
155
|
static get connection() {
|
|
146
156
|
if (!this._connection) {
|
|
147
|
-
this._connection =
|
|
157
|
+
this._connection = this.buildConnection();
|
|
148
158
|
}
|
|
149
159
|
return this._connection;
|
|
150
160
|
}
|
|
@@ -297,8 +307,13 @@ class BaseRecord extends Model {
|
|
|
297
307
|
}
|
|
298
308
|
|
|
299
309
|
|
|
310
|
+
static get redisClientFactory() {
|
|
311
|
+
return redisClientFactory;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
|
|
300
315
|
static async _getRedisClient() {
|
|
301
|
-
const client = redisClientFactory();
|
|
316
|
+
const client = this.redisClientFactory();
|
|
302
317
|
await client.connect();
|
|
303
318
|
return client;
|
|
304
319
|
}
|
|
@@ -13,9 +13,34 @@ class Connection {
|
|
|
13
13
|
#options;
|
|
14
14
|
|
|
15
15
|
constructor(databaseId, options={}) {
|
|
16
|
-
this.#databaseId
|
|
17
|
-
this.#
|
|
18
|
-
|
|
16
|
+
this.#databaseId = databaseId || DEFAULT_DATABASE_ID;
|
|
17
|
+
this.#options = options;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
/***********************************************************************************************
|
|
22
|
+
* COLLABORATOR SEAMS
|
|
23
|
+
***********************************************************************************************/
|
|
24
|
+
get ormEngineClass() {
|
|
25
|
+
return Sequelize;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
get configurationClass() {
|
|
30
|
+
return ConnectionConfiguration;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
get queryInterfaceClass() {
|
|
35
|
+
return QueryInterface;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
get configuration() {
|
|
40
|
+
if (!this.#configuration) {
|
|
41
|
+
this.#configuration = new this.configurationClass(this.#databaseId);
|
|
42
|
+
}
|
|
43
|
+
return this.#configuration;
|
|
19
44
|
}
|
|
20
45
|
|
|
21
46
|
|
|
@@ -38,14 +63,14 @@ class Connection {
|
|
|
38
63
|
|
|
39
64
|
|
|
40
65
|
get queryInterface() {
|
|
41
|
-
return new
|
|
66
|
+
return new this.queryInterfaceClass(this);
|
|
42
67
|
}
|
|
43
68
|
|
|
44
69
|
|
|
45
70
|
get _sequelize() {
|
|
46
71
|
if (sequelizeConnectionsCache[this.#databaseId]) return sequelizeConnectionsCache[this.#databaseId];
|
|
47
72
|
|
|
48
|
-
const connection = new
|
|
73
|
+
const connection = new this.ormEngineClass(null, null, null, this.sequelizeOptions);
|
|
49
74
|
sequelizeConnectionsCache[this.#databaseId] = connection;
|
|
50
75
|
|
|
51
76
|
return connection;
|
|
@@ -76,34 +101,34 @@ class Connection {
|
|
|
76
101
|
|
|
77
102
|
get postgresSequelizeOptions() {
|
|
78
103
|
const options = {
|
|
79
|
-
pool: this
|
|
104
|
+
pool: this.configuration.pool,
|
|
80
105
|
};
|
|
81
106
|
|
|
82
107
|
const primaryConfig = {
|
|
83
|
-
database: this
|
|
84
|
-
host: this
|
|
85
|
-
password: this
|
|
86
|
-
port: this
|
|
87
|
-
username: this
|
|
108
|
+
database: this.configuration.database,
|
|
109
|
+
host: this.configuration.host,
|
|
110
|
+
password: this.configuration.password,
|
|
111
|
+
port: this.configuration.port,
|
|
112
|
+
username: this.configuration.username
|
|
88
113
|
};
|
|
89
114
|
|
|
90
|
-
if (this
|
|
115
|
+
if (this.configuration.readers.length) {
|
|
91
116
|
options.replication = {
|
|
92
117
|
write: primaryConfig,
|
|
93
|
-
read: this
|
|
118
|
+
read: this.configuration.readers
|
|
94
119
|
}
|
|
95
120
|
} else {
|
|
96
121
|
Object.assign(options, primaryConfig);
|
|
97
122
|
}
|
|
98
123
|
|
|
99
|
-
if (this
|
|
124
|
+
if (this.configuration.ssl) options.dialectOptions = {ssl: {require: true}};
|
|
100
125
|
return options;
|
|
101
126
|
}
|
|
102
127
|
|
|
103
128
|
|
|
104
129
|
get sqliteSequelizeOptions() {
|
|
105
130
|
return {
|
|
106
|
-
storage: this
|
|
131
|
+
storage: this.configuration.storage
|
|
107
132
|
};
|
|
108
133
|
}
|
|
109
134
|
|
|
@@ -112,12 +137,12 @@ class Connection {
|
|
|
112
137
|
if (this.#options.hasOwnProperty('loggingEnabled')) {
|
|
113
138
|
return this.#options.loggingEnabled;
|
|
114
139
|
}
|
|
115
|
-
return this
|
|
140
|
+
return this.configuration.loggingEnabled;
|
|
116
141
|
}
|
|
117
142
|
|
|
118
143
|
|
|
119
144
|
get dialect() {
|
|
120
|
-
return this
|
|
145
|
+
return this.configuration.dialect;
|
|
121
146
|
}
|
|
122
147
|
}
|
|
123
148
|
|
|
@@ -6,35 +6,65 @@ const { logger } = require('../../logger');
|
|
|
6
6
|
const { Sequelize } = require('sequelize');
|
|
7
7
|
const utils = require('../utils');
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
class SchemaFileGenerator {
|
|
10
|
+
get connectionClass() {
|
|
11
|
+
return Connection;
|
|
12
|
+
}
|
|
13
|
+
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
await generateSchemaFilesForDatabase(databaseId);
|
|
15
|
+
get databaseIds() {
|
|
16
|
+
return ConnectionConfiguration.configuredDatabaseIds();
|
|
15
17
|
}
|
|
16
|
-
};
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
async
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
async run() {
|
|
21
|
+
utils.ensureSchemasDirectory();
|
|
22
|
+
for (const databaseId of this.databaseIds) {
|
|
23
|
+
await this.generateForDatabase(databaseId);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
buildConnection(databaseId) {
|
|
29
|
+
return new this.connectionClass(databaseId, {loggingEnabled: false});
|
|
30
|
+
}
|
|
31
|
+
|
|
24
32
|
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
async generateForDatabase(databaseId) {
|
|
34
|
+
this.connectionClass.clearConnectionsCache();
|
|
35
|
+
const tables = await this.fetchTables(databaseId);
|
|
36
|
+
this.writeSchemaFile(databaseId, tables);
|
|
37
|
+
}
|
|
27
38
|
|
|
28
|
-
|
|
39
|
+
|
|
40
|
+
async fetchTables(databaseId) {
|
|
41
|
+
const connection = this.buildConnection(databaseId);
|
|
42
|
+
return await connection.queryInterface.allTables();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
writeSchemaFile(databaseId, tables) {
|
|
47
|
+
const filePath = filePathForSchemaFile(databaseId);
|
|
48
|
+
const schemas = `module.exports = ${JSON.stringify(tables, null, 4)};`;
|
|
49
|
+
fs.writeFile(filePath, schemas, err => this.handleWriteResult(err, filePath));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
handleWriteResult(err, filePath) {
|
|
29
54
|
if (err) {
|
|
30
55
|
logger.error(`Unable to write new schema file to ${filePath}`);
|
|
31
56
|
} else {
|
|
32
|
-
logger.info(`New schemas file written to ${filePath}`);
|
|
57
|
+
logger.info(`New schemas file written to ${filePath}`);
|
|
33
58
|
}
|
|
34
|
-
}
|
|
59
|
+
}
|
|
35
60
|
}
|
|
36
61
|
|
|
37
62
|
|
|
63
|
+
async function generateActiveRecordSchemaFiles() {
|
|
64
|
+
await new SchemaFileGenerator().run();
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
|
|
38
68
|
function getActiveRecordSchema(tableName, databaseId, dialect) {
|
|
39
69
|
const filePath = filePathForSchemaFile(databaseId);
|
|
40
70
|
const schema = importSchema(filePath, tableName);
|
|
@@ -108,6 +138,7 @@ function filePathForSchemaFile(databaseId) {
|
|
|
108
138
|
|
|
109
139
|
|
|
110
140
|
module.exports = {
|
|
141
|
+
SchemaFileGenerator,
|
|
111
142
|
generateActiveRecordSchemaFiles,
|
|
112
143
|
getActiveRecordSchema
|
|
113
144
|
};
|
|
@@ -20,8 +20,13 @@ class AbstractJob {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
static get queueResolver() {
|
|
24
|
+
return getQueue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
23
28
|
static queue(...jobArgs) {
|
|
24
|
-
return
|
|
29
|
+
return this.queueResolver(this.queueName(...jobArgs));
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
|
|
@@ -43,8 +48,18 @@ class AbstractJob {
|
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
|
|
51
|
+
get loggerLibrary() {
|
|
52
|
+
return logger;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
get apm() {
|
|
57
|
+
return APM;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
46
61
|
get logger() {
|
|
47
|
-
return
|
|
62
|
+
return this.loggerLibrary[this.constructor.name].child(this.id);
|
|
48
63
|
}
|
|
49
64
|
|
|
50
65
|
|
|
@@ -57,12 +72,12 @@ class AbstractJob {
|
|
|
57
72
|
* APM
|
|
58
73
|
***********************************************************************************************/
|
|
59
74
|
addApmAttribute(key, value) {
|
|
60
|
-
|
|
75
|
+
this.apm.addCustomAttribute(key, value);
|
|
61
76
|
}
|
|
62
77
|
|
|
63
78
|
|
|
64
79
|
startApmSegment(name, record, handler) {
|
|
65
|
-
return
|
|
80
|
+
return this.apm.startSegment(name, record, handler);
|
|
66
81
|
}
|
|
67
82
|
|
|
68
83
|
|
package/lib/jobQueue/queue.js
CHANGED
|
@@ -18,12 +18,15 @@ class Queue extends AbstractJobComponent {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
get queueName()
|
|
22
|
-
get
|
|
21
|
+
get queueName() { return this.#queueName }
|
|
22
|
+
get loggerLibrary() { return logger }
|
|
23
|
+
get logger() { return this.loggerLibrary.queue.child(this.fullQueueName) }
|
|
24
|
+
get queueClass() { return BullMQ.Queue }
|
|
25
|
+
get idGenerator() { return randomUUID }
|
|
23
26
|
|
|
24
27
|
|
|
25
28
|
async queueJob(job, args, settings) {
|
|
26
|
-
const id =
|
|
29
|
+
const id = this.idGenerator();
|
|
27
30
|
await this.#queue.add(job.name, { id, args }, settings);
|
|
28
31
|
}
|
|
29
32
|
|
|
@@ -34,7 +37,7 @@ class Queue extends AbstractJobComponent {
|
|
|
34
37
|
get #queue() {
|
|
35
38
|
if (this.#_queue) return this.#_queue;
|
|
36
39
|
|
|
37
|
-
this.#_queue = new
|
|
40
|
+
this.#_queue = new this.queueClass(this.fullQueueName, this.queueOptions);
|
|
38
41
|
this.#_queue.on('error', this.#handleError.bind(this));
|
|
39
42
|
|
|
40
43
|
return this.#_queue
|
|
@@ -157,5 +160,6 @@ function getQueue(name) {
|
|
|
157
160
|
|
|
158
161
|
|
|
159
162
|
module.exports = {
|
|
163
|
+
Queue,
|
|
160
164
|
getQueue
|
|
161
165
|
}
|
package/lib/jobQueue/worker.js
CHANGED
|
@@ -54,8 +54,18 @@ class Worker extends AbstractJobComponent {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
|
|
57
|
+
get loggerLibrary() {
|
|
58
|
+
return logger;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
get apm() {
|
|
63
|
+
return APM;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
57
67
|
get logger() {
|
|
58
|
-
return
|
|
68
|
+
return this.loggerLibrary.worker;
|
|
59
69
|
}
|
|
60
70
|
|
|
61
71
|
|
|
@@ -67,12 +77,17 @@ class Worker extends AbstractJobComponent {
|
|
|
67
77
|
/***********************************************************************************************
|
|
68
78
|
* WORKER SETUP
|
|
69
79
|
***********************************************************************************************/
|
|
80
|
+
get workerClass() {
|
|
81
|
+
return BullMQ.Worker;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
70
85
|
get #worker() {
|
|
71
86
|
if (this.#_worker) return this.#_worker;
|
|
72
87
|
|
|
73
|
-
this.#_worker = new
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
this.#_worker = new this.workerClass(this.fullQueueName,
|
|
89
|
+
this.processJob.bind(this),
|
|
90
|
+
this.workerOptions);
|
|
76
91
|
this.#setupEventHandling();
|
|
77
92
|
|
|
78
93
|
return this.#_worker;
|
|
@@ -108,9 +123,9 @@ class Worker extends AbstractJobComponent {
|
|
|
108
123
|
if (!jobClass) throw `Unknown Job: ${bullJob.name}`;
|
|
109
124
|
|
|
110
125
|
const context = this.#buildJobContext(bullJob, jobClass);
|
|
111
|
-
return await
|
|
112
|
-
|
|
113
|
-
|
|
126
|
+
return await this.apm.startBackgroundTransaction(context.jobName,
|
|
127
|
+
this.fullQueueName,
|
|
128
|
+
() => this.#runJob(context));
|
|
114
129
|
}
|
|
115
130
|
|
|
116
131
|
|
|
@@ -149,25 +164,25 @@ class Worker extends AbstractJobComponent {
|
|
|
149
164
|
async #executeJob(context) {
|
|
150
165
|
const { bullJob, jobClass, id, args, jobName } = context;
|
|
151
166
|
const job = new jobClass();
|
|
152
|
-
await
|
|
153
|
-
|
|
154
|
-
|
|
167
|
+
await this.apm.startSegment(`job:${jobName}`,
|
|
168
|
+
true,
|
|
169
|
+
() => job._run(id, args, bullJob.updateProgress.bind(bullJob)));
|
|
155
170
|
}
|
|
156
171
|
|
|
157
172
|
|
|
158
173
|
#addJobAttributes(context) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
174
|
+
this.apm.addCustomAttribute('jobId', context.id);
|
|
175
|
+
this.apm.addCustomAttribute('jobName', context.jobName);
|
|
176
|
+
this.apm.addCustomAttribute('queueName', context.queueName);
|
|
177
|
+
this.apm.addCustomAttribute('attempt', context.attempt);
|
|
178
|
+
this.apm.addCustomAttribute('maxAttempts', context.maxAttempts);
|
|
164
179
|
}
|
|
165
180
|
|
|
166
181
|
|
|
167
182
|
#reportJobError(err, context) {
|
|
168
183
|
const isFinalRetry = context.attempt >= context.maxAttempts;
|
|
169
184
|
|
|
170
|
-
|
|
185
|
+
this.apm.reportError(err, {
|
|
171
186
|
jobId: context.id,
|
|
172
187
|
jobName: context.jobName,
|
|
173
188
|
queueName: context.queueName,
|
|
@@ -181,7 +196,7 @@ class Worker extends AbstractJobComponent {
|
|
|
181
196
|
|
|
182
197
|
|
|
183
198
|
#recordJobFailedEvent(context, err) {
|
|
184
|
-
|
|
199
|
+
this.apm.recordCustomEvent(JOB_FAILED_EVENT, {
|
|
185
200
|
jobName: context.jobName,
|
|
186
201
|
queueName: context.queueName,
|
|
187
202
|
attempts: context.attempt,
|
|
@@ -191,13 +206,13 @@ class Worker extends AbstractJobComponent {
|
|
|
191
206
|
|
|
192
207
|
|
|
193
208
|
#recordJobSuccess(context, duration) {
|
|
194
|
-
|
|
209
|
+
this.apm.recordCustomEvent(JOB_COMPLETED_EVENT, {
|
|
195
210
|
jobName: context.jobName,
|
|
196
211
|
queueName: context.queueName,
|
|
197
212
|
durationMs: duration,
|
|
198
213
|
attempts: context.attempt,
|
|
199
214
|
});
|
|
200
|
-
|
|
215
|
+
this.apm.recordMetric(durationMetricName(context.queueName, context.jobName), duration);
|
|
201
216
|
}
|
|
202
217
|
|
|
203
218
|
|
|
@@ -247,7 +262,7 @@ class Worker extends AbstractJobComponent {
|
|
|
247
262
|
|
|
248
263
|
#loggerForJob(bullJob) {
|
|
249
264
|
const { id } = this.#dataForJob(bullJob);
|
|
250
|
-
return logger.
|
|
265
|
+
return this.logger.child(id);
|
|
251
266
|
}
|
|
252
267
|
|
|
253
268
|
|
package/lib/logger/index.js
CHANGED
|
@@ -92,13 +92,17 @@ class Logger {
|
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
#createLogger(scopes, id) {
|
|
95
|
-
scopes
|
|
96
|
-
scopes
|
|
97
|
-
const
|
|
98
|
-
if (loggers[key]) return loggers[key];
|
|
95
|
+
scopes = Array.isArray(scopes) ? scopes : [scopes];
|
|
96
|
+
scopes = scopes.map(scope => scope.toLowerCase());
|
|
97
|
+
const cacheKey = scopes.join('|');
|
|
99
98
|
|
|
100
|
-
loggers[
|
|
101
|
-
|
|
99
|
+
if (!id && loggers[cacheKey]) return loggers[cacheKey];
|
|
100
|
+
|
|
101
|
+
const logger = new Logger(scopes, id);
|
|
102
|
+
|
|
103
|
+
if (!id) loggers[cacheKey] = logger;
|
|
104
|
+
|
|
105
|
+
return logger;
|
|
102
106
|
}
|
|
103
107
|
|
|
104
108
|
|
|
@@ -1,41 +1,56 @@
|
|
|
1
1
|
const expressWinston = require('express-winston');
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
class LoggingMiddleware {
|
|
5
|
+
#logger;
|
|
6
|
+
#middleware;
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
constructor(logger) {
|
|
10
|
+
this.#logger = logger;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
get loggerMiddlewareClass() {
|
|
15
|
+
return expressWinston;
|
|
10
16
|
}
|
|
11
17
|
|
|
12
|
-
const responseTime = res.responseTime || '-';
|
|
13
|
-
const requestDetails = `req: ${req.method} ${req.url.split('?')[0]} for ${req.ip}`;
|
|
14
|
-
const responseDetails = `res: statusCode=${res.statusCode} responseTime=${responseTime}ms`;
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
get middleware() {
|
|
20
|
+
if (!this.#middleware) {
|
|
21
|
+
this.#middleware = this.loggerMiddlewareClass.logger({
|
|
22
|
+
dynamicMeta: (req, res) => ({ id: req.id }),
|
|
23
|
+
level: 'debug',
|
|
24
|
+
msg: this.msgFormatter.bind(this),
|
|
25
|
+
winstonInstance: this.#logger._winstonLogger,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return this.#middleware;
|
|
19
30
|
}
|
|
20
31
|
|
|
21
|
-
return msg;
|
|
22
|
-
};
|
|
23
32
|
|
|
33
|
+
msgFormatter(req, res) {
|
|
34
|
+
const baseMessage = this.requestMessage(req, res);
|
|
35
|
+
const requestDetails = `req: ${req.method} ${req.url.split('?')[0]} for ${req.ip}`;
|
|
36
|
+
const responseTime = res.responseTime || '-';
|
|
37
|
+
const responseDetails = `res: statusCode=${res.statusCode} responseTime=${responseTime}ms`;
|
|
24
38
|
|
|
25
|
-
let
|
|
39
|
+
let msg = `${baseMessage}\n ${requestDetails}\n ${responseDetails}`;
|
|
40
|
+
if (res.error) msg = `${msg}\n${res.error.stack}`;
|
|
26
41
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
42
|
+
return msg;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
requestMessage(req, res) {
|
|
47
|
+
if (req.controller) return `${req.controller.constructor.name}#${req.action}`;
|
|
48
|
+
if (res.statusCode >= 500) return 'request errored';
|
|
49
|
+
return 'request completed';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
37
52
|
|
|
38
53
|
|
|
39
54
|
module.exports = {
|
|
40
|
-
|
|
55
|
+
LoggingMiddleware
|
|
41
56
|
}
|
package/lib/server/server.js
CHANGED
|
@@ -3,10 +3,10 @@ const cookieParser = require('cookie-parser');
|
|
|
3
3
|
const { ControllerImporter } = require('./controllerImporter');
|
|
4
4
|
const express = require('express');
|
|
5
5
|
const { logger } = require('../logger');
|
|
6
|
-
const
|
|
6
|
+
const { LoggingMiddleware } = require('../logger/serverMiddleware');
|
|
7
7
|
const mustacheExpress = require('mustache-express');
|
|
8
8
|
const responseTime = require('response-time');
|
|
9
|
-
const IoServer = require("socket.io")
|
|
9
|
+
const IoServer = require("socket.io");
|
|
10
10
|
const { Server } = require('http');
|
|
11
11
|
const { SystemController } = require('./systemController');
|
|
12
12
|
const requestID = require( 'express-request-id');
|
|
@@ -50,9 +50,14 @@ class VidaServer {
|
|
|
50
50
|
/***********************************************************************************************
|
|
51
51
|
* WEB SOCKETS
|
|
52
52
|
***********************************************************************************************/
|
|
53
|
+
get socketServerFactory() {
|
|
54
|
+
return IoServer;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
53
58
|
get #ioServer() {
|
|
54
59
|
if (!this.#_ioServer) {
|
|
55
|
-
this.#_ioServer =
|
|
60
|
+
this.#_ioServer = this.socketServerFactory(this.#httpServer, {
|
|
56
61
|
cors: { origin: this.corsOrigins, credentials: true }
|
|
57
62
|
});
|
|
58
63
|
}
|
|
@@ -79,9 +84,9 @@ class VidaServer {
|
|
|
79
84
|
this.use(this.octetStreamParsingMiddleware);
|
|
80
85
|
this.use(responseTime({suffix: true}))
|
|
81
86
|
this.use(cookieParser());
|
|
82
|
-
this.use(
|
|
87
|
+
this.use(this.serverEngineFactory.static('public'))
|
|
83
88
|
this.use(this.loggingMiddleware);
|
|
84
|
-
this.use('/static',
|
|
89
|
+
this.use('/static', this.serverEngineFactory.static(this.staticFilesDirectory));
|
|
85
90
|
this.use(this.connectionAbortedMiddleware);
|
|
86
91
|
this.use(requestID());
|
|
87
92
|
|
|
@@ -90,7 +95,7 @@ class VidaServer {
|
|
|
90
95
|
|
|
91
96
|
|
|
92
97
|
get jsonParsingMiddleware() {
|
|
93
|
-
return
|
|
98
|
+
return this.serverEngineFactory.json({
|
|
94
99
|
limit: '50Mb', // Increase JSON limit
|
|
95
100
|
parameterLimit: 50000, // Increase parameter limit
|
|
96
101
|
type: [
|
|
@@ -102,7 +107,7 @@ class VidaServer {
|
|
|
102
107
|
|
|
103
108
|
|
|
104
109
|
get octetStreamParsingMiddleware() {
|
|
105
|
-
return
|
|
110
|
+
return this.serverEngineFactory.raw({ type: 'application/octet-stream', limit: this.octetStreamLimit });
|
|
106
111
|
}
|
|
107
112
|
|
|
108
113
|
|
|
@@ -112,7 +117,7 @@ class VidaServer {
|
|
|
112
117
|
|
|
113
118
|
|
|
114
119
|
get loggingMiddleware() {
|
|
115
|
-
return
|
|
120
|
+
return new LoggingMiddleware(this.logger).middleware;
|
|
116
121
|
}
|
|
117
122
|
|
|
118
123
|
|
|
@@ -235,14 +240,24 @@ class VidaServer {
|
|
|
235
240
|
}
|
|
236
241
|
|
|
237
242
|
|
|
243
|
+
get serverEngineFactory() {
|
|
244
|
+
return express;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
get httpServerFactory() {
|
|
249
|
+
return Server;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
|
|
238
253
|
get #expressServer() {
|
|
239
|
-
if (!this.#_expressServer) this.#_expressServer =
|
|
254
|
+
if (!this.#_expressServer) this.#_expressServer = this.serverEngineFactory();
|
|
240
255
|
return this.#_expressServer;
|
|
241
256
|
}
|
|
242
257
|
|
|
243
258
|
|
|
244
259
|
get #httpServer() { // Needed for io socket to work
|
|
245
|
-
if (!this.#_httpServer) this.#_httpServer =
|
|
260
|
+
if (!this.#_httpServer) this.#_httpServer = this.httpServerFactory(this.#expressServer);
|
|
246
261
|
return this.#_httpServer;
|
|
247
262
|
}
|
|
248
263
|
|
|
@@ -36,7 +36,7 @@ class VidaServerController {
|
|
|
36
36
|
***********************************************************************************************/
|
|
37
37
|
async performRequest(action) {
|
|
38
38
|
try {
|
|
39
|
-
|
|
39
|
+
this.setControllerNameForAPM(action)
|
|
40
40
|
await this.#performRequest(action)
|
|
41
41
|
} catch(err) {
|
|
42
42
|
await this.#handleError(err);
|
|
@@ -44,6 +44,11 @@ class VidaServerController {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
|
|
47
|
+
setControllerNameForAPM(action) {
|
|
48
|
+
APM.setControllerName(this.constructor.name, action);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
47
52
|
async #performRequest(action) {
|
|
48
53
|
await this.#setupRequestState()
|
|
49
54
|
if (this.rendered) return this.#response.end();
|