frosty 0.0.149 → 0.0.150

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frosty",
3
- "version": "0.0.149",
3
+ "version": "0.0.150",
4
4
  "main": "dist/index",
5
5
  "module": "dist/index",
6
6
  "types": "dist/index",
@@ -44,6 +44,7 @@ print_usage() {
44
44
  echo " -B, --no-build Skip build step"
45
45
  echo " -p, --port <port> Specify port for the server (default: 8080)"
46
46
  echo " -n, --num-workers <count> Specify number of worker processes"
47
+ echo " -i, --instance-var <name> Specify the env variable name for worker instance index (default: NODE_APP_INSTANCE)"
47
48
  echo " -c, --configuration <file> Specify configuration file to use (default: server.config.js)"
48
49
  echo " -s, --src <dir> Specify source root directory"
49
50
  echo " -o, --output <dir> Specify output directory for build artifacts"
@@ -66,6 +67,7 @@ while [ $# -gt 0 ]; do
66
67
  -B|--no-build) NO_BUILD=true; shift ;;
67
68
  -p|--port) PORT="$2"; shift 2 ;;
68
69
  -n|--num-workers) NUM_WORKERS="$2"; shift 2 ;;
70
+ -i|--instance-var) INSTANCE_VAR="$2"; shift 2 ;;
69
71
  -c|--configuration) CONFIG_FILE="$2"; shift 2 ;;
70
72
  -s|--src) SRCROOT="$2"; shift 2 ;;
71
73
  -o|--output) OUTPUT_DIR="$2"; shift 2 ;;
@@ -114,6 +116,7 @@ if [ "$NO_BUILD" != "true" ]; then
114
116
  [ -n "$INPUT_FILE" ] && BUILD_OPTS="$BUILD_OPTS --env INPUT_FILE="$INPUT_FILE""
115
117
  [ -n "$SRCROOT" ] && BUILD_OPTS="$BUILD_OPTS --env SRCROOT="$SRCROOT""
116
118
  [ -n "$NUM_WORKERS" ] && BUILD_OPTS="$BUILD_OPTS --env NUM_WORKERS="$NUM_WORKERS""
119
+ [ -n "$INSTANCE_VAR" ] && BUILD_OPTS="$BUILD_OPTS --env INSTANCE_VAR="$INSTANCE_VAR""
117
120
  [ -n "$PORT" ] && BUILD_OPTS="$BUILD_OPTS --env PORT="$PORT""
118
121
  if [ "$WATCH_MODE" = "true" ]; then
119
122
  node "$FROSTY_CLI_ROOT/node_modules/webpack-cli/bin/cli.js" $BUILD_OPTS --watch &
@@ -28,3 +28,4 @@ import { availableParallelism } from 'os';
28
28
 
29
29
  export const PORT = process.env.PORT ? parseInt(process.env.PORT) : 8080;
30
30
  export const NUM_WORKERS = process.env.NUM_WORKERS ? parseInt(process.env.NUM_WORKERS) : availableParallelism();
31
+ export const INSTANCE_VAR = process.env.INSTANCE_VAR || 'NODE_APP_INSTANCE';
@@ -31,18 +31,44 @@ import { Server } from '@o2ter/server-js';
31
31
  import { FrostyRoute } from './route';
32
32
  import * as __SERVER__ from '__SERVER__';
33
33
  import * as __APPLICATIONS__ from '__APPLICATIONS__';
34
- import { PORT, NUM_WORKERS } from './env';
34
+ import { PORT, NUM_WORKERS, INSTANCE_VAR } from './env';
35
35
 
36
36
  if (cluster.isPrimary && NUM_WORKERS > 1) {
37
- console.log(`Primary ${process.pid} is running`);
37
+ console.info(`Primary ${process.pid} is running`);
38
38
 
39
- // Fork workers.
40
- for (let i = 0; i < NUM_WORKERS; i++) {
41
- cluster.fork();
42
- }
39
+ // Fork workers one by one, waiting for each to come online before starting the next.
40
+ let forked = 0;
41
+ const workerInstances = new Map(); // worker.id -> instance index
42
+ const startedWorkers = new Set(); // worker IDs that have successfully started
43
+
44
+ const spawnWorker = (instance) => {
45
+ const worker = cluster.fork({ [INSTANCE_VAR]: instance });
46
+ workerInstances.set(worker.id, instance);
47
+ return worker;
48
+ };
49
+
50
+ const forkNext = () => {
51
+ if (forked >= NUM_WORKERS) return;
52
+ const instance = forked++;
53
+ const worker = spawnWorker(instance);
54
+ worker.once('listening', () => {
55
+ startedWorkers.add(worker.id);
56
+ forkNext();
57
+ });
58
+ };
59
+ forkNext();
43
60
 
44
61
  cluster.on('exit', (worker, code, signal) => {
45
- console.log(`Worker ${worker.process.pid} died`);
62
+ console.info(`Process ${worker.process.pid} exited with code ${code} (${signal})`);
63
+ const instance = workerInstances.get(worker.id);
64
+ workerInstances.delete(worker.id);
65
+ if (startedWorkers.delete(worker.id)) {
66
+ // Worker had started successfully; restart it
67
+ const newWorker = spawnWorker(instance);
68
+ newWorker.once('listening', () => {
69
+ startedWorkers.add(newWorker.id);
70
+ });
71
+ }
46
72
  });
47
73
 
48
74
  } else {
@@ -43,6 +43,7 @@ export default async (env, argv) => {
43
43
  INPUT_FILE,
44
44
  PORT = 8080,
45
45
  NUM_WORKERS,
46
+ INSTANCE_VAR,
46
47
  } = env;
47
48
 
48
49
  const serverConfig = await (async () => {
@@ -254,7 +255,7 @@ export default async (env, argv) => {
254
255
  optimization: webpackOptimization({ server: true }),
255
256
  plugins: _.compact([
256
257
  ...webpackPlugins,
257
- new webpack.EnvironmentPlugin({ PORT, NUM_WORKERS }),
258
+ new webpack.EnvironmentPlugin({ PORT, NUM_WORKERS, INSTANCE_VAR }),
258
259
  new webpack.DefinePlugin({
259
260
  __applications__: JSON.stringify(_.mapValues(inputs, x => ({
260
261
  path: x.basepath,