diff options
Diffstat (limited to 'src/config.js')
-rw-r--r-- | src/config.js | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/config.js b/src/config.js new file mode 100644 index 0000000..9ee6338 --- /dev/null +++ b/src/config.js @@ -0,0 +1,119 @@ +const fs = require('fs') +const ini = require('ini') +const {isNumeric} = require('./util') + +let workerConfig = { + targets: {}, +} +let masterConfig = {} + +function readFile(file) { + if (!fs.existsSync(file)) + throw new Error(`file ${file} not found`) + + return ini.parse(fs.readFileSync(file, 'utf-8')) +} + +function processScheme(source, scheme) { + const result = {} + + for (let key in scheme) { + let opts = scheme[key] + let ne = !(key in source) || !source[key] + if (opts.required === true && ne) + throw new Error(`'${key}' is not defined`) + + let value = source[key] ?? opts.default ?? null + + switch (opts.type) { + case 'int': + if (!isNumeric(value)) + throw new Error(`'${key}' must be an integer`) + value = parseInt(value, 10) + break + + case 'float': + if (!isNumeric(value)) + throw new Error(`'${key}' must be a float`) + value = parseFloat(value) + break + } + + result[key] = value + } + + return result +} + +function parseWorkerConfig(file) { + const raw = readFile(file) + + const scheme = { + host: {required: true}, + port: {required: true, type: 'int'}, + password: {}, + + master_host: {}, + master_port: {type: 'int', default: 0}, + master_reconnect_timeout: {type: 'int', default: 10}, + + log_file: {}, + log_level_file: {default: 'warn'}, + log_level_console: {default: 'warn'}, + + mysql_host: {required: true}, + mysql_port: {required: true, type: 'int'}, + mysql_user: {required: true}, + mysql_password: {required: true}, + mysql_database: {required: true}, + mysql_table: {required: true, default: 'jobs'}, + mysql_fetch_limit: {default: 100, type: 'int'}, + + launcher: {required: true}, + max_output_buffer: {default: 1024*1024, type: 'int'}, + } + Object.assign(workerConfig, processScheme(raw, scheme)) + + // targets + for (let target in raw) { + if (target === 'null') + throw new Error('word \'null\' is reserved, please don\'t use it as a target name') + + if (typeof raw[target] !== 'object') + continue + + workerConfig.targets[target] = {slots: {}} + for (let slotName in raw[target]) { + let slotLimit = parseInt(raw[target][slotName], 10) + if (slotLimit < 1) + throw new Error(`${target}: slot ${slotName} has invalid limit`) + workerConfig.targets[target].slots[slotName] = slotLimit + } + } +} + +function parseMasterConfig(file) { + const raw = readFile(file) + + const scheme = { + host: {required: true}, + port: {required: true, type: 'int'}, + password: {}, + + ping_interval: {default: 30, type: 'int'}, + poke_throttle_interval: {default: 0.5, type: 'float'}, + + log_file: {}, + log_level_file: {default: 'warn'}, + log_level_console: {default: 'warn'}, + } + Object.assign(masterConfig, processScheme(raw, scheme)) +} + +module.exports = { + parseWorkerConfig, + parseMasterConfig, + + workerConfig, + masterConfig +}
\ No newline at end of file |