@naturalcycles/backend-lib 6.0.0 → 6.2.0
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/dist/deploy/deploy.util.js +1 -1
- package/dist/server/createDefaultApp.js +4 -3
- package/dist/server/genericErrorMiddleware.js +2 -2
- package/dist/server/startServer.js +16 -10
- package/dist/server/startServer.model.d.ts +5 -0
- package/package.json +1 -1
- package/src/deploy/deploy.util.ts +2 -2
- package/src/server/createDefaultApp.ts +4 -3
- package/src/server/genericErrorMiddleware.ts +2 -2
- package/src/server/startServer.model.ts +6 -0
- package/src/server/startServer.ts +21 -11
|
@@ -49,7 +49,7 @@ async function createDeployInfo(backendCfg, overrideBranch) {
|
|
|
49
49
|
// Obfuscates the branch name by hashing it.
|
|
50
50
|
// If there are Jira issue names in the branch name, the first one found will be used as a prefix.
|
|
51
51
|
const jiraIssue = gitBranch.match(/([Dd][Ee][Vv]-\d+)/)?.[0];
|
|
52
|
-
const branchHash = (0, nodejs_lib_1.
|
|
52
|
+
const branchHash = (0, nodejs_lib_1.sha256)(gitBranch).slice(0, 10);
|
|
53
53
|
branchName = [jiraIssue, branchHash].filter(Boolean).join('-');
|
|
54
54
|
}
|
|
55
55
|
gaeService = validateGAEServiceName([branchName, gaeService].join('--'));
|
|
@@ -75,9 +75,10 @@ function createDefaultApp(cfg) {
|
|
|
75
75
|
useHandlers(app, cfg.postHandlers);
|
|
76
76
|
// Generic 404 handler
|
|
77
77
|
app.use((0, notFoundMiddleware_1.notFoundMiddleware)());
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
//
|
|
78
|
+
// currently disabled as not necessary (because genericErrorMiddleware already reports to sentry)
|
|
79
|
+
// if (sentryService) {
|
|
80
|
+
// sentryService.sentry.setupExpressErrorHandler(app)
|
|
81
|
+
// }
|
|
81
82
|
// Generic error handler
|
|
82
83
|
// It handles errors, returns proper status, does sentry.captureException(),
|
|
83
84
|
// assigns err.data.errorId from sentry
|
|
@@ -36,7 +36,7 @@ function genericErrorMiddleware(cfg = {}) {
|
|
|
36
36
|
function respondWithError(req, res, err) {
|
|
37
37
|
const { headersSent } = res;
|
|
38
38
|
if (headersSent) {
|
|
39
|
-
req.error(`after headersSent
|
|
39
|
+
req.error(`error after headersSent:`, err);
|
|
40
40
|
}
|
|
41
41
|
else {
|
|
42
42
|
req.error(err);
|
|
@@ -46,7 +46,7 @@ function respondWithError(req, res, err) {
|
|
|
46
46
|
if (sentryService && shouldReportToSentry(originalError)) {
|
|
47
47
|
errorId = sentryService.captureException(originalError, false);
|
|
48
48
|
}
|
|
49
|
-
if (
|
|
49
|
+
if (headersSent)
|
|
50
50
|
return;
|
|
51
51
|
const httpError = (0, js_lib_1._errorLikeToErrorObject)(originalError);
|
|
52
52
|
if (!includeErrorStack)
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.BackendServer = void 0;
|
|
4
4
|
exports.startServer = startServer;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
|
+
const node_os_1 = tslib_1.__importDefault(require("node:os"));
|
|
6
7
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
7
8
|
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
8
9
|
const index_1 = require("../index");
|
|
@@ -12,16 +13,18 @@ class BackendServer {
|
|
|
12
13
|
this.cfg = cfg;
|
|
13
14
|
}
|
|
14
15
|
async start() {
|
|
15
|
-
const { port: cfgPort, expressApp = (0, index_1.createDefaultApp)(this.cfg) } = this.cfg;
|
|
16
|
+
const { port: cfgPort, expressApp = (0, index_1.createDefaultApp)(this.cfg), registerUncaughtExceptionHandlers = true, } = this.cfg;
|
|
16
17
|
// 1. Register error handlers, etc.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
if (registerUncaughtExceptionHandlers) {
|
|
19
|
+
process.on('uncaughtException', err => {
|
|
20
|
+
console.error('BackendServer uncaughtException:', err);
|
|
21
|
+
this.cfg.sentryService?.captureException(err, false);
|
|
22
|
+
});
|
|
23
|
+
process.on('unhandledRejection', err => {
|
|
24
|
+
console.error('BackendServer unhandledRejection:', err);
|
|
25
|
+
this.cfg.sentryService?.captureException(err, false);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
25
28
|
process.once('SIGINT', () => this.stop('SIGINT'));
|
|
26
29
|
process.once('SIGTERM', () => this.stop('SIGTERM'));
|
|
27
30
|
// sentryService.install()
|
|
@@ -46,7 +49,10 @@ class BackendServer {
|
|
|
46
49
|
address = `http://${addr.address}:${port}`;
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
|
-
|
|
52
|
+
const cpus = node_os_1.default.cpus().length;
|
|
53
|
+
const availableParallelism = node_os_1.default.availableParallelism?.();
|
|
54
|
+
const { version, platform, arch } = process;
|
|
55
|
+
console.log((0, nodejs_lib_1.dimGrey)(`node ${version} ${platform} ${arch}, NODE_OPTIONS: ${NODE_OPTIONS || 'undefined'}, APP_ENV: ${APP_ENV || 'undefined'}, cpus: ${cpus}, availableParallelism: ${availableParallelism}`));
|
|
50
56
|
console.log(`serverStarted on ${(0, nodejs_lib_1.white)(address)} in ${(0, nodejs_lib_1.dimGrey)((0, js_lib_1._ms)(process.uptime() * 1000))}`);
|
|
51
57
|
return {
|
|
52
58
|
port,
|
|
@@ -21,6 +21,11 @@ export interface StartServerCfg extends DefaultAppCfg {
|
|
|
21
21
|
*/
|
|
22
22
|
forceShutdownTimeout?: number;
|
|
23
23
|
sentryService?: SentrySharedService;
|
|
24
|
+
/**
|
|
25
|
+
* Defaults to true.
|
|
26
|
+
* Set to false if you already have your handlers elsewhere and don't need them here.
|
|
27
|
+
*/
|
|
28
|
+
registerUncaughtExceptionHandlers?: boolean;
|
|
24
29
|
}
|
|
25
30
|
export interface StartServerData {
|
|
26
31
|
port: number;
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _assert, _mapValues, _merge, _truncate, localTime } from '@naturalcycles/js-lib'
|
|
2
|
-
import { dimGrey, fs2,
|
|
2
|
+
import { dimGrey, fs2, sha256, white } from '@naturalcycles/nodejs-lib'
|
|
3
3
|
import { BackendCfg } from './backend.cfg.util'
|
|
4
4
|
import { AppYaml, DeployInfo } from './deploy.model'
|
|
5
5
|
|
|
@@ -63,7 +63,7 @@ export async function createDeployInfo(
|
|
|
63
63
|
// Obfuscates the branch name by hashing it.
|
|
64
64
|
// If there are Jira issue names in the branch name, the first one found will be used as a prefix.
|
|
65
65
|
const jiraIssue = gitBranch.match(/([Dd][Ee][Vv]-\d+)/)?.[0]
|
|
66
|
-
const branchHash =
|
|
66
|
+
const branchHash = sha256(gitBranch).slice(0, 10)
|
|
67
67
|
branchName = [jiraIssue, branchHash].filter(Boolean).join('-')
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -110,9 +110,10 @@ export function createDefaultApp(cfg: DefaultAppCfg): BackendApplication {
|
|
|
110
110
|
// Generic 404 handler
|
|
111
111
|
app.use(notFoundMiddleware())
|
|
112
112
|
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
113
|
+
// currently disabled as not necessary (because genericErrorMiddleware already reports to sentry)
|
|
114
|
+
// if (sentryService) {
|
|
115
|
+
// sentryService.sentry.setupExpressErrorHandler(app)
|
|
116
|
+
// }
|
|
116
117
|
|
|
117
118
|
// Generic error handler
|
|
118
119
|
// It handles errors, returns proper status, does sentry.captureException(),
|
|
@@ -66,7 +66,7 @@ export function respondWithError(req: BackendRequest, res: BackendResponse, err:
|
|
|
66
66
|
const { headersSent } = res
|
|
67
67
|
|
|
68
68
|
if (headersSent) {
|
|
69
|
-
req.error(`after headersSent
|
|
69
|
+
req.error(`error after headersSent:`, err)
|
|
70
70
|
} else {
|
|
71
71
|
req.error(err)
|
|
72
72
|
}
|
|
@@ -79,7 +79,7 @@ export function respondWithError(req: BackendRequest, res: BackendResponse, err:
|
|
|
79
79
|
errorId = sentryService.captureException(originalError, false)
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
if (
|
|
82
|
+
if (headersSent) return
|
|
83
83
|
|
|
84
84
|
const httpError = _errorLikeToErrorObject(originalError)
|
|
85
85
|
if (!includeErrorStack) delete httpError.stack
|
|
@@ -26,6 +26,12 @@ export interface StartServerCfg extends DefaultAppCfg {
|
|
|
26
26
|
forceShutdownTimeout?: number
|
|
27
27
|
|
|
28
28
|
sentryService?: SentrySharedService
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Defaults to true.
|
|
32
|
+
* Set to false if you already have your handlers elsewhere and don't need them here.
|
|
33
|
+
*/
|
|
34
|
+
registerUncaughtExceptionHandlers?: boolean
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
export interface StartServerData {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Server } from 'node:http'
|
|
2
|
+
import os from 'node:os'
|
|
2
3
|
import { _Memo, _ms } from '@naturalcycles/js-lib'
|
|
3
4
|
import { boldGrey, dimGrey, white } from '@naturalcycles/nodejs-lib'
|
|
4
5
|
import { createDefaultApp } from '../index'
|
|
@@ -12,18 +13,24 @@ export class BackendServer {
|
|
|
12
13
|
server?: Server
|
|
13
14
|
|
|
14
15
|
async start(): Promise<StartServerData> {
|
|
15
|
-
const {
|
|
16
|
+
const {
|
|
17
|
+
port: cfgPort,
|
|
18
|
+
expressApp = createDefaultApp(this.cfg),
|
|
19
|
+
registerUncaughtExceptionHandlers = true,
|
|
20
|
+
} = this.cfg
|
|
16
21
|
|
|
17
22
|
// 1. Register error handlers, etc.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
if (registerUncaughtExceptionHandlers) {
|
|
24
|
+
process.on('uncaughtException', err => {
|
|
25
|
+
console.error('BackendServer uncaughtException:', err)
|
|
26
|
+
this.cfg.sentryService?.captureException(err, false)
|
|
27
|
+
})
|
|
22
28
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
process.on('unhandledRejection', err => {
|
|
30
|
+
console.error('BackendServer unhandledRejection:', err)
|
|
31
|
+
this.cfg.sentryService?.captureException(err, false)
|
|
32
|
+
})
|
|
33
|
+
}
|
|
27
34
|
|
|
28
35
|
process.once('SIGINT', () => this.stop('SIGINT'))
|
|
29
36
|
process.once('SIGTERM', () => this.stop('SIGTERM'))
|
|
@@ -54,11 +61,14 @@ export class BackendServer {
|
|
|
54
61
|
}
|
|
55
62
|
}
|
|
56
63
|
|
|
64
|
+
const cpus = os.cpus().length
|
|
65
|
+
const availableParallelism = os.availableParallelism?.()
|
|
66
|
+
const { version, platform, arch } = process
|
|
57
67
|
console.log(
|
|
58
68
|
dimGrey(
|
|
59
|
-
`node ${
|
|
69
|
+
`node ${version} ${platform} ${arch}, NODE_OPTIONS: ${NODE_OPTIONS || 'undefined'}, APP_ENV: ${
|
|
60
70
|
APP_ENV || 'undefined'
|
|
61
|
-
}`,
|
|
71
|
+
}, cpus: ${cpus}, availableParallelism: ${availableParallelism}`,
|
|
62
72
|
),
|
|
63
73
|
)
|
|
64
74
|
console.log(`serverStarted on ${white(address)} in ${dimGrey(_ms(process.uptime() * 1000))}`)
|