import AgentConfig from "../common/data/AgentConfig"; import ConfigManager from "./ConfigManager"; import * as http from "http"; import ConfigUpdateListener from "./ConfigUpdateListener"; import ConfigOrError from "./ConfigOrError"; import SDKVersion from "../SDKVersion"; import { ConfigErrorCode } from "../common/constant/ShortloopCommonConstant"; import AgentConfigUtils from "../common/utils/AgentConfigUtils"; import { getRequest } from "../common/utils/RequestExecutor"; import SDKLogger from "../SDKLogger"; class SimpleConfigManager implements ConfigManager { private readonly ctUrl: string; private readonly userApplicationName: string; private configUpdateListeners: ConfigUpdateListener[] = []; private executionerService: NodeJS.Timer | undefined; private readonly agentId: string; constructor(ctUrl: string, userApplicationName: string, agentId: string) { this.ctUrl = ctUrl; this.userApplicationName = userApplicationName; this.agentId = agentId; } subscribeToUpdates(configUpdateListener: ConfigUpdateListener): boolean { this.configUpdateListeners.push(configUpdateListener); return true; } getUri(): string { return "/api/v1/agent-config"; } init(): boolean { try { this.scheduleConfigRefresh(60); return true; } catch (e) { SDKLogger.error("While initializing config manager: " + e); return false; } } private scheduleConfigRefresh(timeInSec: number): void { this.executionerService = setTimeout(() => { this.fetchConfigNotify(); }, timeInSec * 1000); } private async fetchConfigNotify(): Promise { let configOrError: ConfigOrError = await this.fetchConfig(); if (configOrError.errorCode) { this.scheduleConfigRefresh(60); this.onUnSuccessfulConfigFetch(); } else { if (configOrError.agentConfig) { this.scheduleConfigRefresh( configOrError.agentConfig.getConfigFetchFreqInSec() ); this.onSuccessfulConfigFetch(configOrError.agentConfig); } } } private onSuccessfulConfigFetch(agentConfig: AgentConfig): void { this.configUpdateListeners.forEach((listener) => { listener.onSuccessfulConfigUpdate(agentConfig); }); } private onUnSuccessfulConfigFetch() { this.configUpdateListeners.forEach((listener) => { listener.onErroneousConfigUpdate(); }); } private async fetchConfig(): Promise { let queryParams: { agentId: string; appName: string; } = { agentId: this.agentId, appName: this.userApplicationName, }; // @ts-ignore let queryString: string = Object.keys(queryParams).map((key) => key + "=" + queryParams[key]).join("&"); let headers: http.OutgoingHttpHeaders = { Accept: "application/json", Connection: "close", ...SDKVersion, }; let url = this.ctUrl + this.getUri() + "?" + queryString; try { let agentConfig: AgentConfig | undefined; await getRequest(url, headers).then((response: any) => { try { agentConfig = new AgentConfig(JSON.parse(response)); } catch (e) { SDKLogger.error("While parsing config response: " + e); } }); if (agentConfig) { if (AgentConfigUtils.isConfigValid(agentConfig)) { return new ConfigOrError(agentConfig, null); } else { SDKLogger.error("Config fetched successfully but invalid"); return new ConfigOrError(null, ConfigErrorCode.INVALID_CONFIG); } } else { return new ConfigOrError(null, ConfigErrorCode.INVALID_CONFIG); } } catch (e) { SDKLogger.error("Error while parsing config: " + e); return new ConfigOrError(null, ConfigErrorCode.PARSE_ERROR); } } shutdown(): boolean { if (this.executionerService) { clearTimeout(this.executionerService); } return true; } } export default SimpleConfigManager;