@naturalcycles/backend-lib 9.62.0 → 9.63.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/dist/bin/deploy-gae.js +7 -7
- package/dist/bin/deploy-health-check.js +5 -5
- package/dist/bin/deploy-prepare.js +3 -3
- package/dist/bin/undeploy-gae.js +3 -3
- package/dist/deploy/deployHealthCheck.d.ts +1 -44
- package/dist/deploy/deployHealthCheck.js +1 -1
- package/dist/deploy/deployPrepare.d.ts +1 -19
- package/dist/deploy/deployPrepare.js +1 -1
- package/dist/express/startServer.d.ts +1 -1
- package/dist/express/startServer.js +8 -3
- package/package.json +5 -5
- package/src/bin/deploy-gae.ts +7 -7
- package/src/bin/deploy-health-check.ts +5 -5
- package/src/bin/deploy-prepare.ts +3 -3
- package/src/bin/undeploy-gae.ts +3 -3
- package/src/deploy/deployHealthCheck.ts +3 -2
- package/src/deploy/deployPrepare.ts +3 -2
- package/src/express/startServer.ts +9 -4
package/dist/bin/deploy-gae.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
import { _parseArgs } from '@naturalcycles/nodejs-lib/args';
|
|
1
2
|
import { runScript } from '@naturalcycles/nodejs-lib/runScript';
|
|
2
|
-
import { _yargs } from '@naturalcycles/nodejs-lib/yargs';
|
|
3
3
|
import { deployGae } from '../deploy/deployGae.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { deployHealthCheckCliOptions } from '../deploy/deployHealthCheck.js';
|
|
5
|
+
import { deployPrepareCliOptions } from '../deploy/deployPrepare.js';
|
|
6
6
|
runScript(async () => {
|
|
7
|
-
const opt =
|
|
8
|
-
...
|
|
9
|
-
...
|
|
10
|
-
})
|
|
7
|
+
const opt = _parseArgs({
|
|
8
|
+
...deployPrepareCliOptions,
|
|
9
|
+
...deployHealthCheckCliOptions,
|
|
10
|
+
});
|
|
11
11
|
await deployGae(opt);
|
|
12
12
|
});
|
|
@@ -6,16 +6,16 @@ yarn deploy-health-check --url https://service-dot-yourproject.appspot.com
|
|
|
6
6
|
--intervalSec 2
|
|
7
7
|
|
|
8
8
|
*/
|
|
9
|
+
import { _parseArgs } from '@naturalcycles/nodejs-lib/args';
|
|
9
10
|
import { runScript } from '@naturalcycles/nodejs-lib/runScript';
|
|
10
|
-
import {
|
|
11
|
-
import { deployHealthCheck, deployHealthCheckYargsOptions } from '../deploy/deployHealthCheck.js';
|
|
11
|
+
import { deployHealthCheck, deployHealthCheckCliOptions } from '../deploy/deployHealthCheck.js';
|
|
12
12
|
runScript(async () => {
|
|
13
|
-
const { url, ...opt } =
|
|
14
|
-
...
|
|
13
|
+
const { url, ...opt } = _parseArgs({
|
|
14
|
+
...deployHealthCheckCliOptions,
|
|
15
15
|
url: {
|
|
16
16
|
type: 'string',
|
|
17
17
|
demandOption: true,
|
|
18
18
|
},
|
|
19
|
-
})
|
|
19
|
+
});
|
|
20
20
|
await deployHealthCheck(url, opt);
|
|
21
21
|
});
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
yarn deploy-prepare
|
|
4
4
|
|
|
5
5
|
*/
|
|
6
|
+
import { _parseArgs } from '@naturalcycles/nodejs-lib/args';
|
|
6
7
|
import { runScript } from '@naturalcycles/nodejs-lib/runScript';
|
|
7
|
-
import {
|
|
8
|
-
import { deployPrepare, deployPrepareYargsOptions } from '../deploy/deployPrepare.js';
|
|
8
|
+
import { deployPrepare, deployPrepareCliOptions } from '../deploy/deployPrepare.js';
|
|
9
9
|
runScript(async () => {
|
|
10
|
-
const opt =
|
|
10
|
+
const opt = _parseArgs(deployPrepareCliOptions);
|
|
11
11
|
await deployPrepare(opt);
|
|
12
12
|
});
|
|
13
13
|
// deploy strategy
|
package/dist/bin/undeploy-gae.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import { _parseArgs } from '@naturalcycles/nodejs-lib/args';
|
|
1
2
|
import { runScript } from '@naturalcycles/nodejs-lib/runScript';
|
|
2
|
-
import { _yargs } from '@naturalcycles/nodejs-lib/yargs';
|
|
3
3
|
import { undeployGae } from '../deploy/deployGae.js';
|
|
4
4
|
runScript(async () => {
|
|
5
|
-
const { branch } =
|
|
5
|
+
const { branch } = _parseArgs({
|
|
6
6
|
branch: {
|
|
7
7
|
type: 'string',
|
|
8
8
|
demandOption: true,
|
|
9
9
|
desc: `Because Github Actions delete event happens after the branch is already deleted - you need to pass it manually`,
|
|
10
10
|
},
|
|
11
|
-
})
|
|
11
|
+
});
|
|
12
12
|
await undeployGae(branch);
|
|
13
13
|
});
|
|
@@ -11,50 +11,7 @@ export interface DeployHealthCheckOptions {
|
|
|
11
11
|
gaeVersion?: string;
|
|
12
12
|
authHeader?: string;
|
|
13
13
|
}
|
|
14
|
-
export declare const
|
|
15
|
-
readonly thresholdHealthy: {
|
|
16
|
-
readonly type: 'number';
|
|
17
|
-
readonly default: 5;
|
|
18
|
-
};
|
|
19
|
-
readonly thresholdUnhealthy: {
|
|
20
|
-
readonly type: 'number';
|
|
21
|
-
readonly default: 8;
|
|
22
|
-
};
|
|
23
|
-
readonly maxTries: {
|
|
24
|
-
readonly type: 'number';
|
|
25
|
-
readonly default: 30;
|
|
26
|
-
};
|
|
27
|
-
readonly timeoutSec: {
|
|
28
|
-
readonly type: 'number';
|
|
29
|
-
readonly default: 180;
|
|
30
|
-
};
|
|
31
|
-
readonly intervalSec: {
|
|
32
|
-
readonly type: 'number';
|
|
33
|
-
readonly default: 1;
|
|
34
|
-
};
|
|
35
|
-
readonly logOnFailure: {
|
|
36
|
-
readonly type: 'boolean';
|
|
37
|
-
readonly default: true;
|
|
38
|
-
readonly desc: 'Show server logs on health check failure (requires gaeProject, gaeService, gaeVersion)';
|
|
39
|
-
};
|
|
40
|
-
readonly logOnSuccess: {
|
|
41
|
-
readonly type: 'boolean';
|
|
42
|
-
readonly default: false;
|
|
43
|
-
readonly desc: 'Show server logs on health check success (requires gaeProject, gaeService, gaeVersion)';
|
|
44
|
-
};
|
|
45
|
-
readonly gaeProject: {
|
|
46
|
-
readonly type: 'string';
|
|
47
|
-
};
|
|
48
|
-
readonly gaeService: {
|
|
49
|
-
readonly type: 'string';
|
|
50
|
-
};
|
|
51
|
-
readonly gaeVersion: {
|
|
52
|
-
readonly type: 'string';
|
|
53
|
-
};
|
|
54
|
-
readonly authHeader: {
|
|
55
|
-
readonly type: 'string';
|
|
56
|
-
};
|
|
57
|
-
};
|
|
14
|
+
export declare const deployHealthCheckCliOptions: CliOptions;
|
|
58
15
|
/**
|
|
59
16
|
* Requires up to `healthyThreshold` consecutive OK responses to succeed.
|
|
60
17
|
* Fails on up to `unhealthyThreshold` consecutive FAIL responses.
|
|
@@ -6,7 +6,7 @@ import { pDelay } from '@naturalcycles/js-lib/promise/pDelay.js';
|
|
|
6
6
|
import { dimGrey, red } from '@naturalcycles/nodejs-lib/colors';
|
|
7
7
|
import { exec2 } from '@naturalcycles/nodejs-lib/exec2';
|
|
8
8
|
import { coloredHttpCode } from '../server/request.log.util.js';
|
|
9
|
-
export const
|
|
9
|
+
export const deployHealthCheckCliOptions = {
|
|
10
10
|
thresholdHealthy: {
|
|
11
11
|
type: 'number',
|
|
12
12
|
default: 5,
|
|
@@ -9,23 +9,5 @@ export interface DeployPrepareOptions {
|
|
|
9
9
|
*/
|
|
10
10
|
appYamlPassEnv?: string;
|
|
11
11
|
}
|
|
12
|
-
export declare const
|
|
13
|
-
readonly projectDir: {
|
|
14
|
-
readonly type: 'string';
|
|
15
|
-
readonly default: '.';
|
|
16
|
-
};
|
|
17
|
-
readonly targetDir: {
|
|
18
|
-
readonly type: 'string';
|
|
19
|
-
readonly default: `./tmp/deploy`;
|
|
20
|
-
};
|
|
21
|
-
readonly createNpmrc: {
|
|
22
|
-
readonly type: 'boolean';
|
|
23
|
-
readonly desc: 'Create .npmrc in targetDir if NPM_TOKEN env var is set';
|
|
24
|
-
readonly default: true;
|
|
25
|
-
};
|
|
26
|
-
readonly appYamlPassEnv: {
|
|
27
|
-
readonly type: 'string';
|
|
28
|
-
readonly desc: 'Comma-separated list of env variables that will be passed to app.yaml from process.env';
|
|
29
|
-
};
|
|
30
|
-
};
|
|
12
|
+
export declare const deployPrepareCliOptions: CliOptions;
|
|
31
13
|
export declare function deployPrepare(opt?: DeployPrepareOptions): Promise<DeployInfo>;
|
|
@@ -5,7 +5,7 @@ import { kpySync } from '@naturalcycles/nodejs-lib/kpy';
|
|
|
5
5
|
import { srcDir } from '../paths.cnst.js';
|
|
6
6
|
import { getBackendCfg } from './backend.cfg.util.js';
|
|
7
7
|
import { createAndSaveAppYaml, createAndSaveDeployInfo } from './deploy.util.js';
|
|
8
|
-
export const
|
|
8
|
+
export const deployPrepareCliOptions = {
|
|
9
9
|
projectDir: {
|
|
10
10
|
type: 'string',
|
|
11
11
|
default: '.',
|
|
@@ -45,8 +45,13 @@ export class BackendServer {
|
|
|
45
45
|
resolve(server);
|
|
46
46
|
});
|
|
47
47
|
});
|
|
48
|
-
// This is to fix GCP LoadBalancer race condition
|
|
49
|
-
|
|
48
|
+
// This is to fix GCP LoadBalancer race condition:
|
|
49
|
+
// GCLB's backend keep-alive timeout is fixed at 600s, and the backend must use
|
|
50
|
+
// a strictly higher value, otherwise the server can close an idle connection at the
|
|
51
|
+
// same moment GCLB reuses it, resulting in intermittent 502s.
|
|
52
|
+
// https://cloud.google.com/load-balancing/docs/https#timeouts_and_retries
|
|
53
|
+
this.server.keepAliveTimeout = 620 * 1000; // slightly above GCLB's 600s
|
|
54
|
+
this.server.headersTimeout = 630 * 1000; // conventionally kept above keepAliveTimeout
|
|
50
55
|
let address = `http://localhost:${port}`; // default
|
|
51
56
|
const addr = this.server.address();
|
|
52
57
|
if (addr) {
|
|
@@ -77,7 +82,7 @@ export class BackendServer {
|
|
|
77
82
|
const shutdownTimeout = setTimeout(() => {
|
|
78
83
|
console.log(boldGrey('Forceful shutdown after timeout'));
|
|
79
84
|
process.exit(0);
|
|
80
|
-
}, this.cfg.forceShutdownTimeout ??
|
|
85
|
+
}, this.cfg.forceShutdownTimeout ?? 8000);
|
|
81
86
|
try {
|
|
82
87
|
await Promise.all([
|
|
83
88
|
this.server && new Promise(r => this.server.close(r)),
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/backend-lib",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "9.
|
|
4
|
+
"version": "9.63.1",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@naturalcycles/db-lib": "^10",
|
|
7
7
|
"@naturalcycles/js-lib": "^15",
|
|
8
8
|
"@naturalcycles/nodejs-lib": "^15",
|
|
9
9
|
"@types/body-parser": "^1",
|
|
10
|
-
"@types/compressible": "^2",
|
|
11
10
|
"@types/cookie-parser": "^1",
|
|
12
11
|
"@types/cors": "^2",
|
|
13
12
|
"@types/express": "^5",
|
|
13
|
+
"@types/compressible": "^2",
|
|
14
14
|
"@types/on-finished": "^2",
|
|
15
15
|
"@types/on-headers": "^1",
|
|
16
16
|
"@types/vary": "^1",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"express": "^5",
|
|
21
21
|
"helmet": "^8",
|
|
22
22
|
"negotiator": "^1",
|
|
23
|
-
"on-finished": "^2",
|
|
24
23
|
"on-headers": "^1",
|
|
24
|
+
"on-finished": "^2",
|
|
25
25
|
"tslib": "^2",
|
|
26
26
|
"vary": "^1"
|
|
27
27
|
},
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@sentry/node-core": "^10",
|
|
46
|
-
"
|
|
46
|
+
"typescript": "rc",
|
|
47
47
|
"fastify": "^5",
|
|
48
|
-
"@naturalcycles/dev-lib": "
|
|
48
|
+
"@naturalcycles/dev-lib": "0.0.0"
|
|
49
49
|
},
|
|
50
50
|
"exports": {
|
|
51
51
|
".": "./dist/index.js",
|
package/src/bin/deploy-gae.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import { _parseArgs } from '@naturalcycles/nodejs-lib/args'
|
|
1
2
|
import { runScript } from '@naturalcycles/nodejs-lib/runScript'
|
|
2
|
-
import { _yargs } from '@naturalcycles/nodejs-lib/yargs'
|
|
3
3
|
import { deployGae } from '../deploy/deployGae.js'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { deployHealthCheckCliOptions } from '../deploy/deployHealthCheck.js'
|
|
5
|
+
import { deployPrepareCliOptions } from '../deploy/deployPrepare.js'
|
|
6
6
|
|
|
7
7
|
runScript(async () => {
|
|
8
|
-
const opt =
|
|
9
|
-
...
|
|
10
|
-
...
|
|
11
|
-
})
|
|
8
|
+
const opt = _parseArgs({
|
|
9
|
+
...deployPrepareCliOptions,
|
|
10
|
+
...deployHealthCheckCliOptions,
|
|
11
|
+
})
|
|
12
12
|
|
|
13
13
|
await deployGae(opt)
|
|
14
14
|
})
|
|
@@ -7,18 +7,18 @@ yarn deploy-health-check --url https://service-dot-yourproject.appspot.com
|
|
|
7
7
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { _parseArgs } from '@naturalcycles/nodejs-lib/args'
|
|
10
11
|
import { runScript } from '@naturalcycles/nodejs-lib/runScript'
|
|
11
|
-
import {
|
|
12
|
-
import { deployHealthCheck, deployHealthCheckYargsOptions } from '../deploy/deployHealthCheck.js'
|
|
12
|
+
import { deployHealthCheck, deployHealthCheckCliOptions } from '../deploy/deployHealthCheck.js'
|
|
13
13
|
|
|
14
14
|
runScript(async () => {
|
|
15
|
-
const { url, ...opt } =
|
|
16
|
-
...
|
|
15
|
+
const { url, ...opt } = _parseArgs({
|
|
16
|
+
...deployHealthCheckCliOptions,
|
|
17
17
|
url: {
|
|
18
18
|
type: 'string',
|
|
19
19
|
demandOption: true,
|
|
20
20
|
},
|
|
21
|
-
})
|
|
21
|
+
})
|
|
22
22
|
|
|
23
23
|
await deployHealthCheck(url, opt)
|
|
24
24
|
})
|
|
@@ -4,12 +4,12 @@ yarn deploy-prepare
|
|
|
4
4
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { _parseArgs } from '@naturalcycles/nodejs-lib/args'
|
|
7
8
|
import { runScript } from '@naturalcycles/nodejs-lib/runScript'
|
|
8
|
-
import {
|
|
9
|
-
import { deployPrepare, deployPrepareYargsOptions } from '../deploy/deployPrepare.js'
|
|
9
|
+
import { deployPrepare, deployPrepareCliOptions } from '../deploy/deployPrepare.js'
|
|
10
10
|
|
|
11
11
|
runScript(async () => {
|
|
12
|
-
const opt =
|
|
12
|
+
const opt = _parseArgs(deployPrepareCliOptions)
|
|
13
13
|
|
|
14
14
|
await deployPrepare(opt)
|
|
15
15
|
})
|
package/src/bin/undeploy-gae.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
import { _parseArgs } from '@naturalcycles/nodejs-lib/args'
|
|
1
2
|
import { runScript } from '@naturalcycles/nodejs-lib/runScript'
|
|
2
|
-
import { _yargs } from '@naturalcycles/nodejs-lib/yargs'
|
|
3
3
|
import { undeployGae } from '../deploy/deployGae.js'
|
|
4
4
|
|
|
5
5
|
runScript(async () => {
|
|
6
|
-
const { branch } =
|
|
6
|
+
const { branch } = _parseArgs({
|
|
7
7
|
branch: {
|
|
8
8
|
type: 'string',
|
|
9
9
|
demandOption: true,
|
|
10
10
|
desc: `Because Github Actions delete event happens after the branch is already deleted - you need to pass it manually`,
|
|
11
11
|
},
|
|
12
|
-
})
|
|
12
|
+
})
|
|
13
13
|
|
|
14
14
|
await undeployGae(branch)
|
|
15
15
|
})
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
} from '@naturalcycles/js-lib/object/object.util.js'
|
|
9
9
|
import { pDelay } from '@naturalcycles/js-lib/promise/pDelay.js'
|
|
10
10
|
import type { UnixTimestampMillis } from '@naturalcycles/js-lib/types'
|
|
11
|
+
import type { CliOptions } from '@naturalcycles/nodejs-lib/args'
|
|
11
12
|
import { dimGrey, red } from '@naturalcycles/nodejs-lib/colors'
|
|
12
13
|
import { exec2 } from '@naturalcycles/nodejs-lib/exec2'
|
|
13
14
|
import { coloredHttpCode } from '../server/request.log.util.js'
|
|
@@ -26,7 +27,7 @@ export interface DeployHealthCheckOptions {
|
|
|
26
27
|
authHeader?: string
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
export const
|
|
30
|
+
export const deployHealthCheckCliOptions = {
|
|
30
31
|
thresholdHealthy: {
|
|
31
32
|
type: 'number',
|
|
32
33
|
default: 5,
|
|
@@ -69,7 +70,7 @@ export const deployHealthCheckYargsOptions = {
|
|
|
69
70
|
authHeader: {
|
|
70
71
|
type: 'string',
|
|
71
72
|
},
|
|
72
|
-
} as const
|
|
73
|
+
} as const satisfies CliOptions
|
|
73
74
|
|
|
74
75
|
const inspectOpt: InspectOptions = {
|
|
75
76
|
colors: true,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { loadEnvFileIfExists } from '@naturalcycles/nodejs-lib'
|
|
2
|
+
import type { CliOptions } from '@naturalcycles/nodejs-lib/args'
|
|
2
3
|
import { dimGrey } from '@naturalcycles/nodejs-lib/colors'
|
|
3
4
|
import { fs2 } from '@naturalcycles/nodejs-lib/fs2'
|
|
4
5
|
import { kpySync } from '@naturalcycles/nodejs-lib/kpy'
|
|
@@ -19,7 +20,7 @@ export interface DeployPrepareOptions {
|
|
|
19
20
|
appYamlPassEnv?: string
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
export const
|
|
23
|
+
export const deployPrepareCliOptions = {
|
|
23
24
|
projectDir: {
|
|
24
25
|
type: 'string',
|
|
25
26
|
default: '.',
|
|
@@ -37,7 +38,7 @@ export const deployPrepareYargsOptions = {
|
|
|
37
38
|
type: 'string',
|
|
38
39
|
desc: 'Comma-separated list of env variables that will be passed to app.yaml from process.env',
|
|
39
40
|
},
|
|
40
|
-
} as const
|
|
41
|
+
} as const satisfies CliOptions
|
|
41
42
|
|
|
42
43
|
const DEFAULT_FILES = [
|
|
43
44
|
'dist',
|
|
@@ -53,8 +53,13 @@ export class BackendServer {
|
|
|
53
53
|
})
|
|
54
54
|
})
|
|
55
55
|
|
|
56
|
-
// This is to fix GCP LoadBalancer race condition
|
|
57
|
-
|
|
56
|
+
// This is to fix GCP LoadBalancer race condition:
|
|
57
|
+
// GCLB's backend keep-alive timeout is fixed at 600s, and the backend must use
|
|
58
|
+
// a strictly higher value, otherwise the server can close an idle connection at the
|
|
59
|
+
// same moment GCLB reuses it, resulting in intermittent 502s.
|
|
60
|
+
// https://cloud.google.com/load-balancing/docs/https#timeouts_and_retries
|
|
61
|
+
this.server.keepAliveTimeout = 620 * 1000 // slightly above GCLB's 600s
|
|
62
|
+
this.server.headersTimeout = 630 * 1000 // conventionally kept above keepAliveTimeout
|
|
58
63
|
|
|
59
64
|
let address = `http://localhost:${port}` // default
|
|
60
65
|
|
|
@@ -97,7 +102,7 @@ export class BackendServer {
|
|
|
97
102
|
const shutdownTimeout = setTimeout(() => {
|
|
98
103
|
console.log(boldGrey('Forceful shutdown after timeout'))
|
|
99
104
|
process.exit(0)
|
|
100
|
-
}, this.cfg.forceShutdownTimeout ??
|
|
105
|
+
}, this.cfg.forceShutdownTimeout ?? 8000)
|
|
101
106
|
|
|
102
107
|
try {
|
|
103
108
|
await Promise.all([
|
|
@@ -146,7 +151,7 @@ export interface StartServerCfg extends DefaultAppCfg {
|
|
|
146
151
|
onShutdown?: () => Promise<void>
|
|
147
152
|
|
|
148
153
|
/**
|
|
149
|
-
* @default
|
|
154
|
+
* @default 8_000
|
|
150
155
|
*/
|
|
151
156
|
forceShutdownTimeout?: number
|
|
152
157
|
|