@freemework/hosting
Version:
Hosting library of the Freemework Project.
186 lines • 8.56 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.flauncher = flauncher;
exports.defaultConfigurationLoader = defaultConfigurationLoader;
exports.registerShutdownHook = registerShutdownHook;
const common_1 = require("@freemework/common");
const index_js_1 = require("../configuration/index.js");
const f_launcher_exception_js_1 = require("./f_launcher_exception.js");
const f_launcher_restart_required_exception_js_1 = require("./f_launcher_restart_required_exception.js");
function flauncher(...args) {
const log = common_1.FLogger.create("FLauncher");
const cancellationTokenSource = new common_1.FCancellationTokenSourceManual();
const executionContext = new common_1.FCancellationExecutionContext(common_1.FExecutionContext.Empty, cancellationTokenSource.token);
async function run() {
process.on("unhandledRejection", (e) => {
const ex = common_1.FException.wrapIfNeeded(e);
log.debug(executionContext, "Unhandled Rejection", ex);
log.fatal(executionContext, `Unhandled Rejection. ${ex.constructor.name}: ${ex.message}`);
fireShutdownHooks().finally(function () {
process.exit(255);
});
});
let destroyRequestCount = 0;
const shutdownSignals = ["SIGTERM", "SIGINT"];
let runtimeStuff;
if (args.length === 3 &&
typeof args[0] === "function" &&
typeof args[1] === "function") {
runtimeStuff = Object.freeze({
loader: args[0],
parser: args[1],
runtimeFactory: args[2],
});
}
else if (args.length === 2 &&
typeof args[0] === "function" &&
typeof args[1] === "function") {
runtimeStuff = Object.freeze({
loader: defaultConfigurationLoader,
parser: args[0],
runtimeFactory: args[1],
});
}
else if (args.length === 1 && typeof args[0] === "function") {
runtimeStuff = Object.freeze({
parser: null,
runtimeFactory: args[0],
});
}
else {
throw new Error("Wrong arguments");
}
let runtime;
if (runtimeStuff.parser === null) {
runtime = await runtimeStuff.runtimeFactory(executionContext);
}
else {
const rawConfiguration = await runtimeStuff.loader(executionContext);
const parsedConfiguration = runtimeStuff.parser(rawConfiguration);
runtime = await runtimeStuff.runtimeFactory(executionContext, parsedConfiguration);
}
shutdownSignals.forEach((signal) => process.on(signal, () => gracefulShutdown(signal)));
async function gracefulShutdown(signal) {
if (destroyRequestCount++ === 0) {
cancellationTokenSource.cancel();
if (log.isInfoEnabled) {
log.info(executionContext, `Interrupt signal received: ${signal}`);
}
try {
await runtime.dispose();
}
catch (e) {
const ex = common_1.FException.wrapIfNeeded(e);
const msg = "Unexpected exception from the dispose() method of your runtime object.";
log.debug(executionContext, msg, ex);
log.error(executionContext, () => `${msg} ${ex.message}`);
}
await fireShutdownHooks();
process.exit(0);
}
else {
if (log.isInfoEnabled) {
log.info(executionContext, `Interrupt signal (${destroyRequestCount}) received: ${signal}`);
}
}
}
}
log.info(executionContext, "Starting application...");
run()
.then(() => {
if (log.isInfoEnabled) {
log.info(executionContext, `Application was started. Process ID: ${process.pid}`);
}
})
.catch((e) => {
const ex = common_1.FException.wrapIfNeeded(e);
if (ex instanceof common_1.FCancellationException) {
log.warn(executionContext, "Runtime initialization was cancelled by user");
fireShutdownHooks().finally(function () {
process.exit(0);
});
}
if (log.isFatalEnabled) {
if (e instanceof f_launcher_exception_js_1.FLauncherException) {
log.fatal(executionContext, `Runtime initialization failed with ${e.constructor.name}: ${e.message}`);
}
else {
log.fatal(executionContext, `Runtime initialization failed with error: ${ex.message}`);
log.debug(executionContext, ex.message, ex);
}
}
const exitCode = ex instanceof f_launcher_restart_required_exception_js_1.FLauncherRestartRequiredException ? ex.exitCode : 127;
if (process.env["NODE_ENV"] === "development") {
setTimeout(() => {
fireShutdownHooks().finally(function () {
process.exit(exitCode);
});
}, 1000);
}
else {
fireShutdownHooks().finally(function () {
process.exit(exitCode);
});
}
});
}
async function defaultConfigurationLoader(_executionContext) {
const chainItems = [];
for (const arg of process.argv) {
if (arg.startsWith(defaultConfigurationLoader.CONFIG_FILE_ARG)) {
const configFile = arg.substring(defaultConfigurationLoader.CONFIG_FILE_ARG.length);
const fileConf = await index_js_1.FConfigurationProperties.fromFile(configFile);
chainItems.push(fileConf);
}
else if (arg.startsWith(defaultConfigurationLoader.CONFIG_TOML_FILE_ARG)) {
const configFile = arg.substring(defaultConfigurationLoader.CONFIG_TOML_FILE_ARG.length);
const fileConf = await index_js_1.FConfigurationToml.fromFile(configFile);
chainItems.push(fileConf);
}
else if (arg.startsWith(defaultConfigurationLoader.CONFIG_SECRET_DIR_ARG)) {
const secretsDir = arg.substring(defaultConfigurationLoader.CONFIG_SECRET_DIR_ARG.length);
const secretsConfiguration = await index_js_1.FConfigurationDirectory.read(secretsDir);
chainItems.push(secretsConfiguration);
}
else if (arg === defaultConfigurationLoader.CONFIG_ENV_ARG) {
const envConf = new index_js_1.FConfigurationEnv();
chainItems.push(envConf);
}
}
if (chainItems.length === 0) {
throw new f_launcher_exception_js_1.FLauncherException("Missing configuration. Please provide at least one of: " +
`${defaultConfigurationLoader.CONFIG_ENV_ARG}, ${defaultConfigurationLoader.CONFIG_FILE_ARG}, ${defaultConfigurationLoader.CONFIG_TOML_FILE_ARG}, ${defaultConfigurationLoader.CONFIG_SECRET_DIR_ARG}`);
}
chainItems.reverse();
const rawConfiguration = new common_1.FConfigurationChain(...chainItems);
return rawConfiguration;
}
(function (defaultConfigurationLoader) {
defaultConfigurationLoader.CONFIG_ENV_ARG = "--config-env";
defaultConfigurationLoader.CONFIG_FILE_ARG = "--config-file=";
defaultConfigurationLoader.CONFIG_TOML_FILE_ARG = "--config-toml-file=";
defaultConfigurationLoader.CONFIG_SECRET_DIR_ARG = "--config-secrets-dir=";
})(defaultConfigurationLoader || (exports.defaultConfigurationLoader = defaultConfigurationLoader = {}));
function registerShutdownHook(cb) {
shutdownHooks.push(cb);
}
const shutdownHooks = [];
async function fireShutdownHooks() {
if (shutdownHooks.length > 0) {
const log = common_1.FLogger.create("FLauncher.fireShutdownHooks");
log.debug(common_1.FExecutionContext.Empty, "Executing shutdown hooks...");
const shutdownHooksCopy = [...shutdownHooks];
do {
const cb = shutdownHooksCopy.pop();
try {
await cb();
}
catch (e) {
const ex = common_1.FException.wrapIfNeeded(e);
log.warn(common_1.FExecutionContext.Empty, `An shutdown hook was finished with error: ${ex.message}`);
log.debug(common_1.FExecutionContext.Empty, "An shutdown hook was finished with error", ex);
}
} while (shutdownHooksCopy.length > 0);
}
}
//# sourceMappingURL=f_launcher.js.map