@imqueue/pg-cache
Version:
PostgreSQL managed cache on Redis for @imqueue-based service methods
98 lines • 3.93 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeChannel = makeChannel;
exports.cacheWith = cacheWith;
/*!
* I'm Queue Software Project
* Copyright (C) 2025 imqueue.com <support@imqueue.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* If you want to use this code in a closed source (commercial) project, you can
* purchase a proprietary commercial license. Please contact us at
* <support@imqueue.com> to get commercial licensing options.
*/
const rpc_1 = require("@imqueue/rpc");
const env_1 = require("./env");
/**
* Makes channel entry from a given channel name, class method name and options.
*
* @access private
* @param {string} name
* @param {string} method
* @param {CacheWithOptions} options
* @return {PgCacheChannel}
*/
function makeChannel(name, method, options) {
return [method, !Array.isArray(options.channels)
? (options.channels)[name]
: undefined,
];
}
/**
* Decorator factory @cacheWith(CacheWithOptions)
* This decorator should be used on a service methods, to set the caching
* rules for a method.
*
* @param {CacheWithOptions} options
* @return {MethodDecorator}
*/
function cacheWith(options) {
return (target, methodName, descriptor) => {
const original = descriptor.value;
const className = typeof target === 'function'
? target.name
: target.constructor.name;
const ttl = options.ttl || env_1.DEFAULT_CACHE_TTL;
const isFiltered = !Array.isArray(options.channels);
const channels = isFiltered
? Object.keys(options.channels)
: options.channels;
target.pgCacheChannels = target.pgCacheChannels || {};
for (const channel of channels) {
const pgChannel = target.pgCacheChannels[channel] =
target.pgCacheChannels[channel] || [];
pgChannel.push(makeChannel(channel, String(methodName), options));
}
descriptor.value = async function (...args) {
const self = this || target;
const cache = self.taggedCache;
const logger = (self.logger || console);
if (!cache) {
(0, env_1.initError)(logger, className, String(methodName), cacheWith);
return original.apply(self, args);
}
const key = (0, rpc_1.signature)(className, methodName, args);
try {
let result = await cache.get(key);
if (result === null || result === undefined) {
result = original.apply(self, args);
if (result && result.then) {
result = await result;
}
const tags = [(0, rpc_1.signature)(className, methodName, [])];
cache.set(key, result, tags, ttl)
.then(res => (0, env_1.setInfo)(logger, res, key, cacheWith))
.catch(err => (0, env_1.setError)(logger, err, key, cacheWith));
}
return result;
}
catch (err) {
(0, env_1.fetchError)(logger, err, key, cacheWith);
return original.apply(self, args);
}
};
};
}
//# sourceMappingURL=cacheWith.js.map