dobi-cache-2
Advanced tools
Comparing version 5.0.0 to 5.0.1
@@ -1,88 +0,37 @@ | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
import { stringify } from 'querystring'; | ||
import RedisDriver from './RedisDriver'; | ||
import { generateCacheData } from './utils'; | ||
var defaultConfig = { | ||
const defaultConfig = { | ||
age: 300, | ||
headers: {}, | ||
query: ['*'] | ||
query: ['*'], | ||
}; | ||
var Index = /** @class */ (function () { | ||
function Index(params) { | ||
class Index { | ||
_enabled; | ||
_redisDriver; | ||
constructor(params) { | ||
this._enabled = params.enabled; | ||
this._redisDriver = new RedisDriver(__assign({ redisModeMap: { "default": 'single' } }, params)); | ||
this._redisDriver = new RedisDriver({ | ||
redisModeMap: { default: 'single' }, | ||
...params, | ||
}); | ||
this.cache = this.cache.bind(this); | ||
} | ||
// force local cache to be max 5 minutes | ||
Index.generateCacheControl = function (age) { | ||
static generateCacheControl(age) { | ||
if (age === 0) { | ||
return 'private, max-age=0, no-cacheHelper, no-store, must-revalidate'; | ||
} | ||
return "public, max-age=".concat(Math.min(age, 300), ", must-revalidate"); | ||
}; | ||
Index.generateConfig = function (rawParams) { | ||
var config = __assign({}, defaultConfig); | ||
return `public, max-age=${Math.min(age, 300)}, must-revalidate`; | ||
} | ||
static generateConfig(rawParams) { | ||
const config = { ...defaultConfig }; | ||
if (!rawParams) { | ||
return config; | ||
} | ||
var params = typeof rawParams === 'string' ? | ||
const params = typeof rawParams === 'string' ? | ||
{ age: rawParams } : rawParams; | ||
// set config.headers | ||
if (params.headers) { | ||
config.headers = __assign({}, params.headers); | ||
config.headers = { ...params.headers }; | ||
} | ||
@@ -92,3 +41,3 @@ // set config.query | ||
if (Array.isArray(params.query)) { | ||
config.query = __spreadArray([], params.query, true); | ||
config.query = [...params.query]; | ||
} | ||
@@ -103,4 +52,4 @@ else if (typeof params.query === 'boolean') { | ||
if (params.age) { | ||
var _a = params.age.split(' '), rawAge = _a[0], type = _a[1]; | ||
var age = Number.parseInt(rawAge, 10); | ||
const [rawAge, type] = params.age.split(' '); | ||
let age = Number.parseInt(rawAge, 10); | ||
switch (type) { | ||
@@ -134,127 +83,102 @@ case 'minute': | ||
return config; | ||
}; | ||
Index.generateKey = function (_a) { | ||
var ctx = _a.ctx, query = _a.query; | ||
var _b = ctx.request, hostname = _b.hostname, path = _b.path, protocol = _b.protocol, requestQuery = _b.query; | ||
var key = "".concat(protocol, "://").concat(hostname).concat(path); | ||
} | ||
static generateKey({ ctx, query }) { | ||
const { hostname, path, protocol, query: requestQuery, } = ctx.request; | ||
let key = `${protocol}://${hostname}${path}`; | ||
if (query.includes('*')) { | ||
var keyQuery = Object.keys(requestQuery).sort().reduce(function (obj, field) { | ||
var _a; | ||
return (__assign(__assign({}, obj), (_a = {}, _a[field] = requestQuery[field], _a))); | ||
}, {}); | ||
key = "".concat(protocol, "://").concat(hostname).concat(path, "?").concat(stringify(keyQuery)); | ||
const keyQuery = Object.keys(requestQuery).sort().reduce((obj, field) => ({ | ||
...obj, | ||
[field]: requestQuery[field], | ||
}), {}); | ||
key = `${protocol}://${hostname}${path}?${stringify(keyQuery)}`; | ||
} | ||
else if (query.length) { | ||
var keyQuery = query.sort().reduce(function (obj, field) { | ||
var _a; | ||
return (__assign(__assign({}, obj), (requestQuery[field] ? (_a = {}, _a[field] = requestQuery[field], _a) : null))); | ||
}, {}); | ||
const keyQuery = query.sort().reduce((obj, field) => ({ | ||
...obj, | ||
...(requestQuery[field] ? { [field]: requestQuery[field] } : null), | ||
}), {}); | ||
if (Object.keys(keyQuery).length) { | ||
key = "".concat(protocol, "://").concat(hostname).concat(path, "?").concat(stringify(keyQuery)); | ||
key = `${protocol}://${hostname}${path}?${stringify(keyQuery)}`; | ||
} | ||
} | ||
return key; | ||
}; | ||
} | ||
// allow fastly to cache however long it needs | ||
Index.generateSurrogateControl = function (age) { | ||
return "max-age=".concat(age); | ||
}; | ||
Index.prototype.cache = function (options) { | ||
var _this = this; | ||
var config = Index.generateConfig(options); | ||
var enabled = this._enabled; | ||
var redisDriver = this._redisDriver; | ||
return function (ctx, next) { return __awaiter(_this, void 0, void 0, function () { | ||
var skipCache, _i, _a, _b, k, v, cacheKey, cacheHeaders, etag, lastModified, cacheData, freshCacheData; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
skipCache = !!ctx.request.query._; | ||
// set headers | ||
for (_i = 0, _a = Object.entries(config.headers); _i < _a.length; _i++) { | ||
_b = _a[_i], k = _b[0], v = _b[1]; | ||
ctx.set(k, v); | ||
} | ||
if (!!(enabled && ['HEAD', 'GET'].includes(ctx.request.method) && !skipCache)) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, next()]; | ||
case 1: | ||
_c.sent(); | ||
return [2 /*return*/]; | ||
case 2: | ||
cacheKey = Index.generateKey({ ctx: ctx, query: config.query }); | ||
// set headers | ||
ctx.set('Cache-Control', Index.generateCacheControl(config.age)); | ||
ctx.set('Surrogate-Control', Index.generateSurrogateControl(config.age)); | ||
ctx.set('Surrogate-Key', "".concat(ctx.request.hostname, " ").concat(cacheKey)); | ||
return [4 /*yield*/, redisDriver.getHeaders(cacheKey)]; | ||
case 3: | ||
cacheHeaders = _c.sent(); | ||
if (cacheHeaders) { | ||
etag = cacheHeaders.etag, lastModified = cacheHeaders.lastModified; | ||
ctx.status = 200; | ||
ctx.response.lastModified = new Date(lastModified); | ||
ctx.response.etag = etag; | ||
if (ctx.fresh) { | ||
ctx.set('X-Dobi-Cache', 'HIT'); | ||
ctx.status = 304; | ||
return [2 /*return*/]; | ||
} | ||
} | ||
return [4 /*yield*/, redisDriver.getData(cacheKey)]; | ||
case 4: | ||
cacheData = _c.sent(); | ||
if (cacheData && cacheData.body && cacheData.type) { | ||
ctx.set('X-Dobi-Cache', 'HIT'); | ||
ctx.set('Content-Type', cacheData.type); | ||
ctx.response.lastModified = new Date(cacheData.lastModified); | ||
ctx.response.etag = cacheData.etag; | ||
// @ts-ignore | ||
ctx.body = cacheData.isBuffer ? Buffer.from(cacheData.body) : cacheData.body; | ||
return [2 /*return*/]; | ||
} | ||
// request missed | ||
return [4 /*yield*/, next()]; | ||
case 5: | ||
// request missed | ||
_c.sent(); | ||
if (!ctx.body) { | ||
return [2 /*return*/]; | ||
} | ||
ctx.set('X-Dobi-Cache', 'MISS'); | ||
return [4 /*yield*/, generateCacheData(ctx)]; | ||
case 6: | ||
freshCacheData = _c.sent(); | ||
return [4 /*yield*/, redisDriver.setHeaders(cacheKey, { | ||
etag: freshCacheData.etag, | ||
lastModified: freshCacheData.lastModified | ||
}, config.age)]; | ||
case 7: | ||
_c.sent(); | ||
return [4 /*yield*/, redisDriver.setData(cacheKey, freshCacheData, config.age)]; | ||
case 8: | ||
_c.sent(); | ||
if (freshCacheData.isBuffer) { | ||
ctx.body = freshCacheData.body; | ||
} | ||
return [2 /*return*/]; | ||
static generateSurrogateControl(age) { | ||
return `max-age=${age}`; | ||
} | ||
cache(options) { | ||
const config = Index.generateConfig(options); | ||
const enabled = this._enabled; | ||
const redisDriver = this._redisDriver; | ||
return async (ctx, next) => { | ||
const skipCache = !!ctx.request.query._; | ||
// set headers | ||
for (const [k, v] of Object.entries(config.headers)) { | ||
ctx.set(k, v); | ||
} | ||
// only cache GETs and HEADs | ||
if (!(enabled && ['HEAD', 'GET'].includes(ctx.request.method) && !skipCache)) { | ||
await next(); | ||
return; | ||
} | ||
// generate key | ||
const cacheKey = Index.generateKey({ ctx, query: config.query }); | ||
// set headers | ||
ctx.set('Cache-Control', Index.generateCacheControl(config.age)); | ||
ctx.set('Surrogate-Control', Index.generateSurrogateControl(config.age)); | ||
ctx.set('Surrogate-Key', `${ctx.request.hostname} ${cacheKey}`); | ||
// check if data is still fresh | ||
const cacheHeaders = await redisDriver.getHeaders(cacheKey); | ||
if (cacheHeaders) { | ||
const { etag, lastModified } = cacheHeaders; | ||
ctx.status = 200; | ||
ctx.response.lastModified = new Date(lastModified); | ||
ctx.response.etag = etag; | ||
if (ctx.fresh) { | ||
ctx.set('X-Dobi-Cache', 'HIT'); | ||
ctx.status = 304; | ||
return; | ||
} | ||
}); | ||
}); }; | ||
}; | ||
Index.prototype.flushCache = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
if (!this._enabled) { | ||
return [2 /*return*/, 0]; | ||
} | ||
return [2 /*return*/, this._redisDriver.flushCache()]; | ||
}); | ||
}); | ||
}; | ||
Index.prototype.getRedisDriver = function () { | ||
} | ||
// check for cached data | ||
const cacheData = await redisDriver.getData(cacheKey); | ||
if (cacheData && cacheData.body && cacheData.type) { | ||
ctx.set('X-Dobi-Cache', 'HIT'); | ||
ctx.set('Content-Type', cacheData.type); | ||
ctx.response.lastModified = new Date(cacheData.lastModified); | ||
ctx.response.etag = cacheData.etag; | ||
// @ts-ignore | ||
ctx.body = cacheData.isBuffer ? Buffer.from(cacheData.body) : cacheData.body; | ||
return; | ||
} | ||
// request missed | ||
await next(); | ||
if (!ctx.body) { | ||
return; | ||
} | ||
ctx.set('X-Dobi-Cache', 'MISS'); | ||
// update cache | ||
const freshCacheData = await generateCacheData(ctx); | ||
await redisDriver.setHeaders(cacheKey, { | ||
etag: freshCacheData.etag, | ||
lastModified: freshCacheData.lastModified, | ||
}, config.age); | ||
await redisDriver.setData(cacheKey, freshCacheData, config.age); | ||
if (freshCacheData.isBuffer) { | ||
ctx.body = freshCacheData.body; | ||
} | ||
}; | ||
} | ||
async flushCache() { | ||
if (!this._enabled) { | ||
return 0; | ||
} | ||
return this._redisDriver.flushCache(); | ||
} | ||
getRedisDriver() { | ||
return this._redisDriver; | ||
}; | ||
return Index; | ||
}()); | ||
} | ||
} | ||
export default Index; | ||
//# sourceMappingURL=index.js.map |
@@ -1,50 +0,3 @@ | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
import Redis from 'ioredis'; | ||
var connectionMap = {}; | ||
const connectionMap = {}; | ||
export var RedisMode; | ||
@@ -55,8 +8,12 @@ (function (RedisMode) { | ||
})(RedisMode || (RedisMode = {})); | ||
var RedisDriver = /** @class */ (function () { | ||
function RedisDriver(params) { | ||
class RedisDriver { | ||
_enabled; | ||
_keyPrefix; | ||
_redis; | ||
_redisMode; | ||
constructor(params) { | ||
this._enabled = params.enabled; | ||
this._keyPrefix = params.keyPrefix; | ||
if (this._enabled) { | ||
var _a = this.getClient(params), client = _a.client, redisMode = _a.redisMode; | ||
const { client, redisMode } = this.getClient(params); | ||
this._redis = client; | ||
@@ -69,224 +26,134 @@ this._redisMode = redisMode; | ||
} | ||
RedisDriver.createInstance = function (redisUri, port, redisMode) { | ||
static createInstance(redisUri, port, redisMode) { | ||
// tslint:disable-next-line:no-console | ||
console.log("[REDIS]: Connecting to ".concat(redisUri, " in ").concat(redisMode, " mode")); | ||
console.log(`[REDIS]: Connecting to ${redisUri} in ${redisMode} mode`); | ||
if (redisMode === 'single') { | ||
return new Redis({ host: redisUri, port: port }); | ||
return new Redis({ host: redisUri, port }); | ||
} | ||
var uris = redisUri.split(','); | ||
var endpoints = []; | ||
for (var _i = 0, uris_1 = uris; _i < uris_1.length; _i++) { | ||
var uri = uris_1[_i]; | ||
const uris = redisUri.split(','); | ||
const endpoints = []; | ||
for (const uri of uris) { | ||
if (uri.indexOf(':')) { | ||
var segments = uri.split(':'); | ||
const segments = uri.split(':'); | ||
endpoints.push({ host: segments[0], port: Number.parseInt(segments[1], 10) || port }); | ||
} | ||
else { | ||
endpoints.push({ host: uri, port: port }); | ||
endpoints.push({ host: uri, port }); | ||
} | ||
} | ||
return new Redis.Cluster(endpoints); | ||
}; | ||
RedisDriver.prototype["delete"] = function (key) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var deleted, _a, _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
if (!this._enabled) { | ||
return [2 /*return*/, 0]; | ||
} | ||
deleted = 0; | ||
_a = deleted; | ||
return [4 /*yield*/, this._redis.del(this.generateHeadersKey(key))]; | ||
case 1: | ||
deleted = _a + _c.sent(); | ||
_b = deleted; | ||
return [4 /*yield*/, this._redis.del(this.generateDataKey(key))]; | ||
case 2: | ||
deleted = _b + _c.sent(); | ||
return [2 /*return*/, deleted]; | ||
} | ||
}); | ||
} | ||
async delete(key) { | ||
if (!this._enabled) { | ||
return 0; | ||
} | ||
let deleted = 0; | ||
deleted += await this._redis.del(this.generateHeadersKey(key)); | ||
deleted += await this._redis.del(this.generateDataKey(key)); | ||
return deleted; | ||
} | ||
async flushCache() { | ||
if (!this._enabled) { | ||
return 0; | ||
} | ||
if (this.isSingleMode()) { | ||
return this.flushCacheOfNode(this._redis); | ||
} | ||
if (this.isClusterMode()) { | ||
const client = this._redis; | ||
const nodes = client.nodes('master'); | ||
let total = 0; | ||
for (const node of nodes) { | ||
const flushed = await this.flushCacheOfNode(node); | ||
total += flushed || 0; | ||
} | ||
return total; | ||
} | ||
return 0; | ||
} | ||
async getData(key) { | ||
return this.get(this.generateDataKey(key)); | ||
} | ||
async getHeaders(key) { | ||
return this.get(this.generateHeadersKey(key)); | ||
} | ||
async setData(key, value, ttl) { | ||
await this.set(this.generateDataKey(key), value, ttl); | ||
} | ||
async setHeaders(key, value, ttl) { | ||
await this.set(this.generateHeadersKey(key), value, ttl); | ||
} | ||
async flushCacheOfNode(node) { | ||
const stream = node.scanStream({ | ||
count: 500, | ||
match: `${this._keyPrefix}*`, | ||
}); | ||
}; | ||
RedisDriver.prototype.flushCache = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var client, nodes, total, _i, nodes_1, node, flushed; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!this._enabled) { | ||
return [2 /*return*/, 0]; | ||
} | ||
if (this.isSingleMode()) { | ||
return [2 /*return*/, this.flushCacheOfNode(this._redis)]; | ||
} | ||
if (!this.isClusterMode()) return [3 /*break*/, 5]; | ||
client = this._redis; | ||
nodes = client.nodes('master'); | ||
total = 0; | ||
_i = 0, nodes_1 = nodes; | ||
_a.label = 1; | ||
case 1: | ||
if (!(_i < nodes_1.length)) return [3 /*break*/, 4]; | ||
node = nodes_1[_i]; | ||
return [4 /*yield*/, this.flushCacheOfNode(node)]; | ||
case 2: | ||
flushed = _a.sent(); | ||
total += flushed || 0; | ||
_a.label = 3; | ||
case 3: | ||
_i++; | ||
return [3 /*break*/, 1]; | ||
case 4: return [2 /*return*/, total]; | ||
case 5: return [2 /*return*/, 0]; | ||
} | ||
}); | ||
let count = 0; | ||
stream.on('data', (keys) => { | ||
if (keys.length) { | ||
count += keys.length; | ||
const pipeline = node.pipeline(); | ||
keys.forEach((key) => pipeline.del(key)); | ||
pipeline.exec(); | ||
} | ||
}); | ||
}; | ||
RedisDriver.prototype.getData = function (key) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, this.get(this.generateDataKey(key))]; | ||
return new Promise((resolve, reject) => { | ||
stream.once('end', () => { | ||
resolve(count); | ||
}); | ||
}); | ||
}; | ||
RedisDriver.prototype.getHeaders = function (key) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, this.get(this.generateHeadersKey(key))]; | ||
stream.once('error', (error) => { | ||
reject(error); | ||
}); | ||
}); | ||
}; | ||
RedisDriver.prototype.setData = function (key, value, ttl) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.set(this.generateDataKey(key), value, ttl)]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
RedisDriver.prototype.setHeaders = function (key, value, ttl) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.set(this.generateHeadersKey(key), value, ttl)]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
RedisDriver.prototype.flushCacheOfNode = function (node) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var stream, count; | ||
return __generator(this, function (_a) { | ||
stream = node.scanStream({ | ||
count: 500, | ||
match: "".concat(this._keyPrefix, "*") | ||
}); | ||
count = 0; | ||
stream.on('data', function (keys) { | ||
if (keys.length) { | ||
count += keys.length; | ||
var pipeline_1 = node.pipeline(); | ||
keys.forEach(function (key) { return pipeline_1.del(key); }); | ||
pipeline_1.exec(); | ||
} | ||
}); | ||
return [2 /*return*/, new Promise(function (resolve, reject) { | ||
stream.once('end', function () { | ||
resolve(count); | ||
}); | ||
stream.once('error', function (error) { | ||
reject(error); | ||
}); | ||
})]; | ||
}); | ||
}); | ||
}; | ||
RedisDriver.prototype.generateBaseKey = function (key) { | ||
return "".concat(this._keyPrefix, ":").concat(key); | ||
}; | ||
RedisDriver.prototype.generateDataKey = function (key) { | ||
return "".concat(this.generateBaseKey(key), ":data"); | ||
}; | ||
RedisDriver.prototype.generateHeadersKey = function (key) { | ||
return "".concat(this.generateBaseKey(key), ":headers"); | ||
}; | ||
RedisDriver.prototype.get = function (key) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var cacheValue, err_1; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!this._enabled) { | ||
return [2 /*return*/, null]; | ||
} | ||
return [4 /*yield*/, this._redis.get(key)]; | ||
case 1: | ||
cacheValue = _a.sent(); | ||
if (!cacheValue) { | ||
return [2 /*return*/, null]; | ||
} | ||
_a.label = 2; | ||
case 2: | ||
_a.trys.push([2, 3, , 5]); | ||
return [2 /*return*/, JSON.parse(cacheValue)]; | ||
case 3: | ||
err_1 = _a.sent(); | ||
return [4 /*yield*/, this["delete"](key)]; | ||
case 4: | ||
_a.sent(); | ||
return [2 /*return*/, null]; | ||
case 5: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
RedisDriver.prototype.getClient = function (_a) { | ||
var _b = _a.redisPort, redisPort = _b === void 0 ? 6379 : _b, redisModeMap = _a.redisModeMap, redisUri = _a.redisUri; | ||
var modeMap = __assign(__assign({}, redisModeMap), { "default": 'single' }); | ||
var redisMode = (modeMap[redisUri || 'default'] || 'single'); | ||
} | ||
generateBaseKey(key) { | ||
return `${this._keyPrefix}:${key}`; | ||
} | ||
generateDataKey(key) { | ||
return `${this.generateBaseKey(key)}:data`; | ||
} | ||
generateHeadersKey(key) { | ||
return `${this.generateBaseKey(key)}:headers`; | ||
} | ||
async get(key) { | ||
if (!this._enabled) { | ||
return null; | ||
} | ||
const cacheValue = await this._redis.get(key); | ||
if (!cacheValue) { | ||
return null; | ||
} | ||
try { | ||
return JSON.parse(cacheValue); | ||
} | ||
catch (err) { | ||
await this.delete(key); | ||
return null; | ||
} | ||
} | ||
getClient({ redisPort = 6379, redisModeMap, redisUri }) { | ||
const modeMap = { ...redisModeMap, default: 'single' }; | ||
const redisMode = (modeMap[redisUri || 'default'] || 'single'); | ||
// reassigning to variable for readability purposes. | ||
var cacheKey = [redisUri, redisMode].join(':'); | ||
const cacheKey = [redisUri, redisMode].join(':'); | ||
if (!connectionMap[cacheKey]) { | ||
connectionMap[cacheKey] = RedisDriver.createInstance(redisUri, redisPort, redisMode); | ||
} | ||
return { client: connectionMap[cacheKey], redisMode: redisMode }; | ||
}; | ||
RedisDriver.prototype.isClusterMode = function () { | ||
return { client: connectionMap[cacheKey], redisMode }; | ||
} | ||
isClusterMode() { | ||
return this._redisMode === RedisMode.CLUSTERED; | ||
}; | ||
RedisDriver.prototype.isSingleMode = function () { | ||
} | ||
isSingleMode() { | ||
return this._redisMode === RedisMode.SINGLE; | ||
}; | ||
RedisDriver.prototype.set = function (key, value, ttl) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!this._enabled) { | ||
return [2 /*return*/]; | ||
} | ||
return [4 /*yield*/, this._redis.set(key, JSON.stringify(value))]; | ||
case 1: | ||
_a.sent(); | ||
return [4 /*yield*/, this._redis.expire(key, ttl)]; | ||
case 2: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
return RedisDriver; | ||
}()); | ||
} | ||
async set(key, value, ttl) { | ||
if (!this._enabled) { | ||
return; | ||
} | ||
await this._redis.set(key, JSON.stringify(value)); | ||
await this._redis.expire(key, ttl); | ||
} | ||
} | ||
export default RedisDriver; | ||
//# sourceMappingURL=RedisDriver.js.map |
@@ -1,63 +0,22 @@ | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
// import isJSON from 'koa-is-json'; | ||
import streamToArray from 'stream-to-array'; | ||
import { createHash } from 'crypto'; | ||
export var generateCacheData = function (ctx) { return __awaiter(void 0, void 0, void 0, function () { | ||
var type, outputBody, streamArray; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
type = ctx.response.get('Content-Type') || null; | ||
outputBody = ctx.body; | ||
if (!(typeof ctx.body.pipe === 'function')) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, streamToArray(outputBody)]; | ||
case 1: | ||
streamArray = _a.sent(); | ||
outputBody = Buffer.concat(streamArray); | ||
_a.label = 2; | ||
case 2: return [2 /*return*/, { | ||
body: outputBody, | ||
etag: createHash('md5').update(outputBody).digest('hex'), | ||
isBuffer: Buffer.isBuffer(outputBody), | ||
lastModified: Date.now(), | ||
type: type | ||
}]; | ||
} | ||
}); | ||
}); }; | ||
export const generateCacheData = async (ctx) => { | ||
const type = ctx.response.get('Content-Type') || null; | ||
let outputBody = ctx.body; | ||
// if (isJSON(ctx.body)) { | ||
// outputBody = JSON.stringify(outputBody); | ||
// } | ||
if (typeof ctx.body.pipe === 'function') { | ||
const streamArray = await streamToArray(outputBody); | ||
outputBody = Buffer.concat(streamArray); | ||
} | ||
return { | ||
body: outputBody, | ||
etag: createHash('md5').update(outputBody).digest('hex'), | ||
isBuffer: Buffer.isBuffer(outputBody), | ||
lastModified: Date.now(), | ||
type, | ||
}; | ||
}; | ||
//# sourceMappingURL=utils.js.map |
@@ -35,3 +35,3 @@ { | ||
}, | ||
"version": "5.0.0", | ||
"version": "5.0.1", | ||
"devDependencies": { | ||
@@ -38,0 +38,0 @@ "@types/koa": "^2.11.0", |
@@ -19,3 +19,3 @@ { | ||
"strictPropertyInitialization": true, | ||
"target": "es3", | ||
"target": "ESNEXT", | ||
"types": ["node"] | ||
@@ -22,0 +22,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25
60458
1025