UNPKG

vulcain-corejs

Version:
216 lines 7.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const rx = require("rxjs"); const dynamicProperty_1 = require("./properties/dynamicProperty"); const PrioritizedSourceValue_1 = require("./sources/PrioritizedSourceValue"); const chainedPropertyValue_1 = require("./properties/chainedPropertyValue"); const fileConfigurationSource_1 = require("./sources/fileConfigurationSource"); const system_1 = require("../globals/system"); const environmentVariableSource_1 = require("./sources/environmentVariableSource"); const files_1 = require("../utils/files"); class ConfigurationManager { constructor(pollingIntervalInSeconds = 60, sourceTimeoutInMs = 1500) { this.pollingIntervalInSeconds = pollingIntervalInSeconds; this.sourceTimeoutInMs = sourceTimeoutInMs; this._dynamicProperties = new Map(); this._environmentVariables = new environmentVariableSource_1.EnvironmentVariableSource(); } get properties() { return this._dynamicProperties; } get propertyChanged() { if (!this._propertyChanged) { this._propertyChanged = new rx.ReplaySubject(1); } return this._propertyChanged; } getValueInSources(name) { if (!this._values) { this._values = new PrioritizedSourceValue_1.PrioritizedSourceValue(); } let val = this._values.get(name); return val; } createDynamicProperty(name, defaultValue) { system_1.Service.registerPropertyAsDependency(name, defaultValue); let dp = new dynamicProperty_1.DynamicProperty(this, name, defaultValue); if (name) { dp.set(this.getValueInSources(name)); } return dp; } createChainedDynamicProperty(name, properties, defaultValue) { system_1.Service.registerPropertyAsDependency(name, defaultValue); properties = properties && properties.filter(n => !!n); // remove null property if (!properties || properties.length === 0) return this.createDynamicProperty(name, defaultValue); let dp = new chainedPropertyValue_1.ChainedDynamicProperty(this, name, properties, defaultValue); dp.set(this.getValueInSources(name)); return dp; } getValueFromEnvironmentVariable(name) { let val = this._environmentVariables.get(name); return val; } getProperty(name) { let prop = this._dynamicProperties.get(name); if (!prop) { let v = this._environmentVariables.get(name); if (v !== undefined) prop = this.createDynamicProperty(name, v); } return prop; } /** * Initialize source(s) and return only when all sources are initialized * @param sources List of sources * @returns {Promise<T>} */ async startPolling(sources = [], pollSources = true) { let localSources = []; let remoteSources = []; if (!Array.isArray(sources)) { sources = [sources]; } sources.push(new fileConfigurationSource_1.FileConfigurationSource(files_1.Files.findConfigurationFile(), fileConfigurationSource_1.ConfigurationDataType.VulcainConfig)); for (let source of sources) { // Local properties has loaded first (less priority) if (source.readProperties) { localSources.push(source); await source.readProperties(); } else { let s = source; if (remoteSources.indexOf(s) < 0) { remoteSources.push(s); } } } this._values = new PrioritizedSourceValue_1.PrioritizedSourceValue(localSources, remoteSources); // Run initialization let tries = 2; while (tries > 0) { if (await this.polling(3000, false)) { // All sources are OK if (pollSources) this.repeatPolling(); this.isRunning = true; return; } tries--; if (tries) system_1.Service.log.info(null, () => "CONFIG: Some dynamic properties sources failed. Retry polling."); } if (!system_1.Service.isDevelopment) { throw new Error("CONFIG: Cannot read properties from sources. Program is stopped."); } else { system_1.Service.log.info(null, () => "CONFIG: Cannot read properties from sources."); } } /** * for test only */ async forcePolling(src, reset) { if (reset) this._values = null; if (src) { if (!this._values) { this._values = new PrioritizedSourceValue_1.PrioritizedSourceValue([], [src]); } else { this._values.remoteSources.push(src); } } await this.polling(3000, false); } /** * Pull properties for all sources * * @private * @param {any} [timeout] * @returns * * @memberOf ConfigurationManager */ async polling(timeout, pollSources = true) { let ok = true; try { let list = this._values.remoteSources; if (this.disposed || !list) return; let promises = []; list.forEach(src => { promises.push( // pollProperties cannot failed src.pollProperties(timeout || this.sourceTimeoutInMs)); }); let results = await Promise.all(promises); // Ignore null result results.forEach(res => { if (!res) { ok = false; } else this.onPropertiesChanged(res); }); } catch (e) { ok = false; system_1.Service.log.error(null, e, () => "CONFIG: Error when polling sources"); } // Restart if (pollSources) this.repeatPolling(); return ok; } onPropertiesChanged(data) { if (!data.values) return; for (let d of data.values) { let dp = this._dynamicProperties.get(d.key); if (!dp) { dp = this.createDynamicProperty(d.key); } else if (dp.updateValue) { dp.updateValue(d); } } } onPropertyChanged(dp) { this._propertyChanged && this._propertyChanged.next(dp); } repeatPolling() { if (!this.disposed && this._values.remoteSources.length > 0) setTimeout(this.polling.bind(this), this.pollingIntervalInSeconds * 1000); } /** /// Reset configuration and properties. /// All current properties will be invalid and all current sources will be lost. /// </summary> /// <param name="pollingIntervalInSeconds"></param> /// <param name="sourceTimeoutInMs"></param> */ reset(pollingIntervalInSeconds, sourceTimeoutInMs) { if (pollingIntervalInSeconds) this.pollingIntervalInSeconds = pollingIntervalInSeconds; if (sourceTimeoutInMs) this.sourceTimeoutInMs = sourceTimeoutInMs; //this._propertyChanged.dispose(); this._propertyChanged = null; let tmp = this._dynamicProperties; if (tmp) { for (let prop of tmp.values()) { if (prop.dispose) prop.dispose(); } tmp.clear(); } } dispose() { this.reset(); this.disposed = true; } } exports.ConfigurationManager = ConfigurationManager; //# sourceMappingURL=configurationManager.js.map