UNPKG

@vulcan-sql/core

Version:
133 lines 6.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CacheLayerRefresher = void 0; const tslib_1 = require("tslib"); const ms_1 = require("ms"); const lodash_1 = require("lodash"); const toad_scheduler_1 = require("toad-scheduler"); const inversify_1 = require("inversify"); const types_1 = require("../../containers/types"); const models_1 = require("../../models/index"); const errors_1 = require("../utils/errors"); const utils_1 = require("../utils"); const moment = require("moment"); var RefreshResult; (function (RefreshResult) { RefreshResult["SUCCESS"] = "SUCCESS"; RefreshResult["FAILED"] = "FAILED"; })(RefreshResult || (RefreshResult = {})); let CacheLayerRefresher = class CacheLayerRefresher { constructor(loader, activityLoggers) { this.scheduler = new toad_scheduler_1.ToadScheduler(); this.logger = (0, utils_1.getLogger)({ scopeName: 'CORE' }); this.cacheLoader = loader; this.activityLoggers = activityLoggers; } start(schemas, runImmediately = true) { return tslib_1.__awaiter(this, void 0, void 0, function* () { // check if the cache table name is duplicated more than one API schemas this.checkDuplicateCacheTableName(schemas); // check if the index name is duplicated more than one API schemas this.checkDuplicateIndex(schemas); // traverse each cache table of each schema yield Promise.all(schemas.map((schema) => tslib_1.__awaiter(this, void 0, void 0, function* () { // skip the schema by return if not set the cache if (!schema.cache) return; return yield Promise.all(schema.cache.map((cache) => tslib_1.__awaiter(this, void 0, void 0, function* () { const { cacheTableName, profile, refreshTime } = cache; // replace the '/' tp '_' to avoid the file path issue for templateSource const templateName = schema.templateSource.replace('/', '_'); // If refresh time is set, use the scheduler to schedule the load task for refresh if (refreshTime === null || refreshTime === void 0 ? void 0 : refreshTime.every) { // use the work id for task to know which failed when execute and get the job to by id. const workerId = `${templateName}/${profile}/${cacheTableName}`; const milliseconds = (0, ms_1.default)(refreshTime.every); const refreshJob = new toad_scheduler_1.SimpleIntervalJob({ milliseconds, runImmediately }, new toad_scheduler_1.AsyncTask(workerId, () => tslib_1.__awaiter(this, void 0, void 0, function* () { yield this.loadCacheAndSendActivityLog(schema, cache); })), { preventOverrun: true, id: workerId }); // add the job to schedule cache refresh task this.scheduler.addIntervalJob(refreshJob); } else { yield this.loadCacheAndSendActivityLog(schema, cache); } }))); }))); }); } /** * Stop the cache layer loader */ stop() { this.scheduler.stop(); } loadCacheAndSendActivityLog(schema, cache) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const { urlPath } = schema; const { sql } = cache; let refreshResult = RefreshResult.SUCCESS; const now = moment.utc().format('YYYY-MM-DD HH:mm:ss'); const templateName = schema.templateSource.replace('/', '_'); try { // get the current time in format of UTC yield this.cacheLoader.load(templateName, cache); } catch (error) { refreshResult = RefreshResult.FAILED; this.logger.debug(`Failed to refresh cache: ${error}`); } finally { // send activity log const content = { isSuccess: refreshResult === RefreshResult.SUCCESS ? true : false, activityLogType: models_1.ActivityLogType.CACHE_REFRESH, logTime: now, urlPath, sql, }; const activityLoggers = this.getActivityLoggers(); for (const activityLogger of activityLoggers) activityLogger.log(content).catch((err) => { this.logger.debug(`Failed to log activity after refreshing cache: ${err}`); }); } }); } getActivityLoggers() { return this.activityLoggers.filter((logger) => logger.isEnabled()); } checkDuplicateCacheTableName(schemas) { const tableNames = schemas // => [[table1, table2], [table1, table3], [table4]] .map((schema) => { var _a; return (_a = schema.cache) === null || _a === void 0 ? void 0 : _a.map((cache) => cache.cacheTableName); }) // => [table1, table2, table1, table3, table4] .flat() // use filter to make sure it has value and pick it. .filter((tableName) => tableName); if ((0, lodash_1.uniq)(tableNames).length !== tableNames.length) throw new errors_1.ConfigurationError('Not allow to set same cache table name more than one API schema.'); } checkDuplicateIndex(schemas) { const indexNames = schemas // => [[table1_idx, table1_idx2, table2_idx], [table1_idx, table3_idx], [table4_idx]] .map((schema) => { var _a; return (_a = schema.cache) === null || _a === void 0 ? void 0 : _a.map((cache) => (cache.indexes ? Object.keys(cache.indexes) : [])).flat(); }) // => [table1_idx, table1_idx2, table2_idx, table1_idx, table3_idx, table4_idx] .flat() // use filter to make sure it has value and pick it. .filter((indexName) => indexName); if ((0, lodash_1.uniq)(indexNames).length !== indexNames.length) throw new errors_1.ConfigurationError('Not allow to set same index name more than one API schema.'); } }; CacheLayerRefresher = tslib_1.__decorate([ (0, inversify_1.injectable)(), tslib_1.__param(0, (0, inversify_1.inject)(types_1.TYPES.CacheLayerLoader)), tslib_1.__param(1, (0, inversify_1.multiInject)(types_1.TYPES.Extension_ActivityLogger)), tslib_1.__metadata("design:paramtypes", [Object, Array]) ], CacheLayerRefresher); exports.CacheLayerRefresher = CacheLayerRefresher; //# sourceMappingURL=cacheLayerRefresher.js.map