Change the application to use the cluster api

- Use the nodejs cluster API
- Use the config package for configuration
- Change config type to toml
pull/2/head
Trivernis 5 years ago
parent 127f9ed045
commit 456e81192c

@ -1,11 +1,11 @@
# http server configuration # http server configuration
server: [server]
port: 8080 port = 8080
# graphql configuration # graphql configuration
graphql: [graphql]
graphiql: true graphiql = true
# logging configuration # logging configuration
logging: [logging]
loglevel: debug loglevel = "debug"

4918
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -4,7 +4,9 @@
"description": "Template for express graphql servers", "description": "Template for express graphql servers",
"main": "./dist", "main": "./dist",
"dependencies": { "dependencies": {
"@types/config": "^0.0.36",
"compression": "^1.7.4", "compression": "^1.7.4",
"config": "^3.2.4",
"express": "^4.17.1", "express": "^4.17.1",
"express-graphql": "^0.9.0", "express-graphql": "^0.9.0",
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
@ -12,6 +14,7 @@
"graphql-import": "^0.7.1", "graphql-import": "^0.7.1",
"http-status": "^1.3.2", "http-status": "^1.3.2",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"toml": "^3.0.0",
"winston": "^3.2.1" "winston": "^3.2.1"
}, },
"devDependencies": { "devDependencies": {

@ -1,15 +1,15 @@
import * as compression from "compression"; import * as compression from "compression";
import * as config from "config";
import * as express from "express"; import * as express from "express";
import * as graphqlHTTP from "express-graphql"; import * as graphqlHTTP from "express-graphql";
import {buildSchema} from "graphql"; import {buildSchema} from "graphql";
import {importSchema} from "graphql-import"; import {importSchema} from "graphql-import";
import * as http from "http"; import * as http from "http";
import * as path from "path"; import * as path from "path";
import globals from "./lib/globals";
import {resolvers} from "./graphql/resolvers"; import {resolvers} from "./graphql/resolvers";
import globals from "./lib/globals";
const logger = globals.logger; const logger = globals.logger;
const config = globals.config;
/** /**
* Main class of the application server. * Main class of the application server.
@ -43,7 +43,7 @@ class App {
}); });
this.app.use("/graphql", graphqlHTTP((request, response) => { this.app.use("/graphql", graphqlHTTP((request, response) => {
return { return {
graphiql: config.graphql.graphiql, graphiql: config.get("graphql.graphiql"),
rootValue: resolvers(request, response), rootValue: resolvers(request, response),
schema: buildSchema(importSchema(path.join(__dirname, "./graphql/schema.graphql"))), schema: buildSchema(importSchema(path.join(__dirname, "./graphql/schema.graphql"))),
}; };
@ -54,10 +54,10 @@ class App {
* Starts the web server. * Starts the web server.
*/ */
public start() { public start() {
if (config.server.port) { if (config.has("server.port")) {
logger.info(`Starting server...`); logger.info(`Starting server...`);
this.app.listen(config.server.port); this.app.listen(config.get("server.port"));
logger.info(`Server running on port ${config.server.port}`); logger.info(`Server running on port ${config.get("server.port")}`);
} else { } else {
logger.error("No port specified in the config." + logger.error("No port specified in the config." +
"Please configure a port in the config.yaml."); "Please configure a port in the config.yaml.");

@ -15,6 +15,6 @@ export function resolvers(req: http.IncomingMessage, res: http.OutgoingMessage)
*/ */
time() { time() {
return (new Date()).toString(); return (new Date()).toString();
} },
} };
} }

@ -1,10 +1,35 @@
// tslint:disable:no-console
process.env.NODE_CONFIG_DIR = __dirname + "/../config";
import App from "./app"; import App from "./app";
const numCPUs = require("os").cpus().length;
import * as cluster from "cluster";
/** if (cluster.isMaster) {
console.log(`[CLUSTER-M] Master ${process.pid} is running`);
cluster.settings.silent = true;
cluster.on("exit", (worker, code) => {
console.error(`[CLUSTER-M] Worker ${worker.id} died! (code: ${code})`);
console.log("[CLUSTER-M] Starting new worker");
cluster.fork();
});
cluster.on("online", (worker) => {
worker.process.stdout.on("data", (data) => {
process.stdout.write(`[CLUSTER-${worker.id}] ${data}`);
});
});
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
/**
* Async main function wrapper. * Async main function wrapper.
*/ */
(async () => { (async () => {
const app = new App(); const app = new App();
await app.init(); await app.init();
app.start(); app.start();
})(); })();
}

@ -1,33 +1,10 @@
/** import * as config from "config";
* @author Trivernis
* @remarks
*
* Partly taken from {@link https://github.com/Trivernis/whooshy}#
*
* Provides global variables that are used in the whole project.
*/
import * as fsx from "fs-extra";
import * as yaml from "js-yaml";
import * as winston from "winston"; import * as winston from "winston";
const configPath = "config.yaml";
const defaultConfig = __dirname + "/../default-config.yaml";
// ensure that the config exists by copying the default config.
if (!(fsx.pathExistsSync(configPath))) {
fsx.copySync(defaultConfig, configPath);
} else {
const conf = yaml.safeLoad(fsx.readFileSync(configPath, "utf-8"));
const defConf = yaml.safeLoad(fsx.readFileSync(defaultConfig, "utf-8"));
fsx.writeFileSync(configPath, yaml.safeDump(Object.assign(defConf, conf)));
}
/** /**
* Defines global variables to be used. * Defines global variables to be used.
*/ */
namespace globals { namespace globals {
export const config = yaml.safeLoad(fsx.readFileSync("config.yaml", "utf-8"));
export const logger = winston.createLogger({ export const logger = winston.createLogger({
transports: [ transports: [
new winston.transports.Console({ new winston.transports.Console({
@ -38,7 +15,7 @@ namespace globals {
return `${timestamp} ${level}: ${message}`; return `${timestamp} ${level}: ${message}`;
}), }),
), ),
level: config.logging.loglevel, level: config.get("logging.loglevel"),
}), }),
], ],
}); });

@ -21,7 +21,15 @@
}, },
"no-namespace": false, "no-namespace": false,
"no-internal-module": false, "no-internal-module": false,
"max-classes-per-file": false "max-classes-per-file": false,
"no-var-requires": false,
"jsdoc-format": [true, "check-multiline-start"],
"completed-docs": [true, "classes", "enums", "methods", {
"properties": {
"privacies": "all",
"locations": "instance"
}
}]
}, },
"jsRules": { "jsRules": {
"max-line-length": { "max-line-length": {

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save