@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.
@@ -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.md5)(gitBranch).slice(0, 10);
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
- // todo: test if it's needed!
79
- // Add this after all routes, but before any and other error-handling middlewares are defined
80
- // Sentry.setupExpressErrorHandler(app);
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`, err);
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 (res.headersSent)
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
- process.on('uncaughtException', err => {
18
- console.error('uncaughtException:', err);
19
- this.cfg.sentryService?.captureException(err, false);
20
- });
21
- process.on('unhandledRejection', err => {
22
- console.error('unhandledRejection:', err);
23
- this.cfg.sentryService?.captureException(err, false);
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
- console.log((0, nodejs_lib_1.dimGrey)(`node ${process.version}, NODE_OPTIONS: ${NODE_OPTIONS || 'undefined'}, APP_ENV: ${APP_ENV || 'undefined'}`));
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/backend-lib",
3
- "version": "6.0.0",
3
+ "version": "6.2.0",
4
4
  "scripts": {
5
5
  "prepare": "husky",
6
6
  "build": "dev-lib build",
@@ -1,5 +1,5 @@
1
1
  import { _assert, _mapValues, _merge, _truncate, localTime } from '@naturalcycles/js-lib'
2
- import { dimGrey, fs2, md5, white } from '@naturalcycles/nodejs-lib'
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 = md5(gitBranch).slice(0, 10)
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
- // todo: test if it's needed!
114
- // Add this after all routes, but before any and other error-handling middlewares are defined
115
- // Sentry.setupExpressErrorHandler(app);
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`, err)
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 (res.headersSent) return
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 { port: cfgPort, expressApp = createDefaultApp(this.cfg) } = this.cfg
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
- process.on('uncaughtException', err => {
19
- console.error('uncaughtException:', err)
20
- this.cfg.sentryService?.captureException(err, false)
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
- process.on('unhandledRejection', err => {
24
- console.error('unhandledRejection:', err)
25
- this.cfg.sentryService?.captureException(err, false)
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 ${process.version}, NODE_OPTIONS: ${NODE_OPTIONS || 'undefined'}, APP_ENV: ${
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))}`)