UNPKG

@5minds/processcube_engine

Version:

The ProcessCube Engine. Stores and executes BPMNs.

289 lines • 12 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.workerThreadNames = exports.workerThreadIds = void 0; exports.registerOnBeforeResumingCallback = registerOnBeforeResumingCallback; exports.clearOnReadyCallbacks = clearOnReadyCallbacks; exports.registerOnReadyCallback = registerOnReadyCallback; exports.getOnBeforeResumingCallbacks = getOnBeforeResumingCallbacks; exports.getOnReadyCallbacks = getOnReadyCallbacks; exports.isSQLite = isSQLite; exports.isWindows = isWindows; exports.getBeautifiedThreadName = getBeautifiedThreadName; exports.getThreadName = getThreadName; exports.getExtensionDir = getExtensionDir; exports.isWindowsAndSQLite = isWindowsAndSQLite; exports.loadConfig = loadConfig; exports.calculateMaxPoolSize = calculateMaxPoolSize; exports.getSqlitePath = getSqlitePath; exports.getUserConfigFolder = getUserConfigFolder; exports.readConfigFile = readConfigFile; exports.getConfig = getConfig; exports.getReleaseChannel = getReleaseChannel; exports.readPackageJson = readPackageJson; exports.setWorkingDirectory = setWorkingDirectory; exports.getWorkingDirectory = getWorkingDirectory; const child_process_1 = require("child_process"); const fs_1 = __importDefault(require("fs")); const os_1 = __importDefault(require("os")); const path_1 = __importDefault(require("path")); const processcube_engine_sdk_1 = require("@5minds/processcube_engine_sdk"); const Configurator_1 = __importDefault(require("./Configurator")); const logger = new processcube_engine_sdk_1.Logger('application'); exports.workerThreadIds = { main: 'main', fetchAndLock: 'fetchAndLock', query: 'query', runtime: 'runtime', }; exports.workerThreadNames = { main: 'main', fetchAndLock: 'ExternalTasks', query: 'QueryRequests', runtime: 'ProcessExecution', }; const dbConnectionWeightsPerThread = { [exports.workerThreadIds.main]: 0, [exports.workerThreadIds.fetchAndLock]: 0.3, [exports.workerThreadIds.query]: 0.3, [exports.workerThreadIds.runtime]: 0.4, }; let thread = exports.workerThreadIds.main; const onBeforeResumingCallbacks = []; let onReadyCallbacks = []; let configuredSqlitePath; let workingDirectory = path_1.default.resolve(path_1.default.join(getUserConfigFolder(), '.processcube', 'engine')); function registerOnBeforeResumingCallback(callback) { onBeforeResumingCallbacks.push(callback); } function clearOnReadyCallbacks() { onReadyCallbacks = []; } function registerOnReadyCallback(callback) { onReadyCallbacks.push(callback); } function getOnBeforeResumingCallbacks() { return onBeforeResumingCallbacks; } function getOnReadyCallbacks() { return onReadyCallbacks; } function isSQLite() { const databaseConfig = Configurator_1.default.database(); return databaseConfig.dialect === 'sqlite'; } function isWindows() { return process.platform === 'win32'; } function getBeautifiedThreadName() { return exports.workerThreadNames[getThreadName()]; } function getThreadName() { return thread; } function getExtensionDir() { const extensionsDir = process.env.extensionsDir || path_1.default.join(workingDirectory, 'extensions'); const normalizedDir = path_1.default.normalize(extensionsDir); return path_1.default.resolve(normalizedDir); } function isWindowsAndSQLite() { return isSQLite() && isWindows(); } async function loadConfig(workerName) { thread = workerName; configuredSqlitePath = process.env.sqlitePath; if (!process.env.appRootDir) { process.env.appRootDir = path_1.default.resolve(__dirname, '..', '..'); } if (!process.env.CONFIG_PATH) { const defaultConfigPath = path_1.default.resolve(process.env.appRootDir, 'configs', 'sqlite.json'); logger.info(`Using Default Config File: '${defaultConfigPath}'`); process.env.CONFIG_PATH = defaultConfigPath; } const configFile = readConfigFile(); setWorkingDirectory(); const sqliteUsed = (process.env.database__dialect || configFile.database.dialect) === 'sqlite'; if (sqliteUsed) { const sqlitePathFromConfig = process.env.database__storage || configFile.database.storage; configureSqlite(configuredSqlitePath ?? sqlitePathFromConfig); } Configurator_1.default.initialize(process.env.CONFIG_PATH, getReleaseChannel()); const minLogLevel = Configurator_1.default.logging()?.minLogLevel; process.env.minLogLevel = minLogLevel || processcube_engine_sdk_1.LogLevel.debug; process.env.hostname = await getHostname(); if (workerName) { (0, processcube_engine_sdk_1.setGlobalLogObjects)({ worker: workerName, }); } } function calculateMaxPoolSize(dbPoolConfig) { if (!dbPoolConfig) { return 0; } validateDatabasePoolSizeSettings(dbPoolConfig); const maxGlobalPoolSizeSet = !!dbPoolConfig.max; const workerSpecificPoolSizesSet = dbPoolConfig.maxForExternalTasks || dbPoolConfig.maxForQueryRequests || dbPoolConfig.maxForProcessExecution; if (maxGlobalPoolSizeSet) { return Math.floor(dbPoolConfig.max * dbConnectionWeightsPerThread[thread]); } if (workerSpecificPoolSizesSet) { switch (thread) { case exports.workerThreadIds.main: return 0; case exports.workerThreadIds.fetchAndLock: return dbPoolConfig.maxForExternalTasks; case exports.workerThreadIds.query: return dbPoolConfig.maxForQueryRequests; case exports.workerThreadIds.runtime: return dbPoolConfig.maxForProcessExecution; } } } function validateDatabasePoolSizeSettings(dbPoolConfig) { const maxGlobalPoolSizeSet = !!dbPoolConfig.max; const workerSpecificPoolSizesSet = dbPoolConfig.maxForExternalTasks || dbPoolConfig.maxForQueryRequests || dbPoolConfig.maxForProcessExecution; const isMissingAWorkerSpecificPoolSize = !(dbPoolConfig.maxForExternalTasks && dbPoolConfig.maxForQueryRequests && dbPoolConfig.maxForProcessExecution); if (maxGlobalPoolSizeSet && workerSpecificPoolSizesSet) { const errorMessage = ` Failure in Setup: Cannot configure an overall "max" db connection pool size in conjunction with worker-specific connection pool sizes. Currentl configuration: ${JSON.stringify(dbPoolConfig)} To fix this, either use database.pool.max OR database.pool.maxForExternalTasks with database.pool.maxForQueryRequests and database.pool.maxForProcessExecution OR remove the settings altogether. Either use "pool": { "max": 100 } OR: "pool": { "maxForExternalTasks": 30, "maxForQueryRequests": 30, "maxForProcessExecution": 40 }`; const conflictingSettingsError = new processcube_engine_sdk_1.UnprocessableEntityError(errorMessage); conflictingSettingsError.category = 'setup'; conflictingSettingsError.additionalInformation = { currentConfiguration: dbPoolConfig, }; throw conflictingSettingsError; } if (workerSpecificPoolSizesSet && isMissingAWorkerSpecificPoolSize) { const errorMessage = ` Failure in Setup: A db connection pool setting is missing. Currently configured: ${JSON.stringify(dbPoolConfig)} To fix this, you must provide values for database.pool.maxForExternalTasks, database.pool.maxForQueryRequests and database.pool.maxForProcessExecution, or you can remove the settings altogether. Example: "pool": { "maxForExternalTasks": 30, "maxForQueryRequests": 30, "maxForProcessExecution": 40 }`; const settingsMissingError = new processcube_engine_sdk_1.UnprocessableEntityError(errorMessage); settingsMissingError.category = 'setup'; settingsMissingError.additionalInformation = { currentConfiguration: dbPoolConfig, }; throw settingsMissingError; } } async function getHostname() { return new Promise((resolve) => { (0, child_process_1.exec)('hostname', (error, result) => { if (error) { logger.warn(`Failed to retrieve hostname: ${error.message}`, { err: error }); return resolve('N/A'); } return resolve(result?.trim()); }); }); } function getSqlitePath() { return configuredSqlitePath; } function getUserConfigFolder() { return os_1.default.homedir(); } function readConfigFile() { const configFilePath = path_1.default.resolve(process.env.CONFIG_PATH); const fileContent = fs_1.default.readFileSync(configFilePath, 'utf-8'); const parsedFileContent = JSON.parse(fileContent); return parsedFileContent; } function getConfig() { return { httpServer: Configurator_1.default.httpServer(), logging: Configurator_1.default.logging(), database: Configurator_1.default.database(), iam: Configurator_1.default.iam(), application: Configurator_1.default.application(), }; } function getReleaseChannel() { const nodeEnv = process.env.NODE_ENV?.toLowerCase(); const isDev = nodeEnv == 'dev' || nodeEnv == 'develop' || nodeEnv == 'development' || nodeEnv == 'test'; if (isDev) { return 'dev'; } const version = readPackageJson().version; if (version.includes('alpha')) { return 'alpha'; } if (version.includes('beta')) { return 'beta'; } return 'stable'; } function readPackageJson() { const pathToPackageJson = path_1.default.join(process.env.appRootDir, 'package.json'); const packageJsonAsString = fs_1.default.readFileSync(pathToPackageJson, 'utf-8'); const packageJson = JSON.parse(packageJsonAsString); return packageJson; } function setWorkingDirectory() { const customWorkDir = process.env.workDir; if (!customWorkDir) { configureDefaultWorkDir(); logger.debug(`Using default working directory: ${workingDirectory}`); return; } const resolvedCustomWorkDir = path_1.default.resolve(customWorkDir); if (!fs_1.default.existsSync(resolvedCustomWorkDir)) { fs_1.default.mkdirSync(resolvedCustomWorkDir, { recursive: true }); } workingDirectory = resolvedCustomWorkDir; logger.debug(`Using working directory: ${workingDirectory}`); } function getWorkingDirectory() { return workingDirectory; } function configureSqlite(customSqliteStoragePath) { configuredSqlitePath = resolveSqliteStoragePath(customSqliteStoragePath); process.env.database__storage = configuredSqlitePath; } function resolveSqliteStoragePath(customSqliteStoragePath) { const defaultSqlitePath = workingDirectory; let pathToUse = path_1.default.isAbsolute(customSqliteStoragePath) ? customSqliteStoragePath : path_1.default.join(defaultSqlitePath, customSqliteStoragePath); if (fs_1.default.existsSync(pathToUse) && fs_1.default.lstatSync(pathToUse).isDirectory()) { pathToUse = path_1.default.join(pathToUse, 'engine.sqlite'); } return path_1.default.resolve(pathToUse); } function configureDefaultWorkDir() { const defaultWorkDir = path_1.default.join(getUserConfigFolder(), '.processcube', 'engine'); const legacyWorkDir = path_1.default.join(getUserConfigFolder(), '.atlas', 'engine'); const legacyWorkDirDoesNotExist = !fs_1.default.existsSync(legacyWorkDir); if (legacyWorkDirDoesNotExist) { workingDirectory = defaultWorkDir; return; } const defaultWorkDirExists = fs_1.default.existsSync(defaultWorkDir); if (defaultWorkDirExists) { throw new Error(`Found both working directories \`${legacyWorkDir}\` and \`${defaultWorkDir}\`.\n\nPlease rename/remove \`${legacyWorkDir}\` in favor of \`${defaultWorkDir}\`.`); } logger.warn(`Using legacy working directory '${legacyWorkDir}'.\n\nPlease rename '${legacyWorkDir}' to '${defaultWorkDir}'.`); workingDirectory = legacyWorkDir; } //# sourceMappingURL=Environment.js.map