axios-cache-adapter
axios-cache-adapter copied to clipboard
Code in documentation fails: `Use redis as cache store`
The code example Use redis as cache store when configured correctly
- Node: 16.6.1
- axios-cache-adapter: 2.7.3
- redis: 6
- Ubuntu: 20.04
The error stems from this code: https://github.com/RasCarlito/axios-cache-adapter/blob/2d51cee4070ff88f2272533f9593fd41a392f52c/src/redis.js#L7-L17
Could this assertion be removed to allow more flexibility and reduce the chance future bugs based on minor version bump changes of variable names?
So digging into the issue more, and the constructor name is Commander
instead of RedisClient
It looks as though node-redis had a major version bump recently, causing this issue. A couple of options:
- Use node-redis v3
- Write your own version of RedisStore, using a redis client of your choosing (ioredis is another option)
@timminss, Is this really a solution though? Would a better solution to be to remove the assertion or to update the documentation?
It's adapter for radis 4.0.4
You can replace import { RedisDefaultStore } from 'axios-cache-adapter'
with import RedisDefaultStore from './RedisDefaultStore';
.
RedisDefaultStore.ts
import { RedisClientType } from 'redis';
import { RedisDefaultOptions } from 'axios-cache-adapter';
interface IEntry {
expires: number;
data: string;
}
class RedisDefaultStore {
private client: RedisClientType;
private prefix: string | any;
private maxScanCount: number;
private getAsync: any;
private psetexAsync: any;
private delAsync: any;
private scanAsync: any;
constructor(
client: RedisClientType | any,
options: RedisDefaultOptions = {},
) {
client.connect();
this.client = client;
this.prefix = options.prefix || 'axios-cache';
this.maxScanCount = options.maxScanCount || 1000;
this.getAsync = client.get.bind(client);
this.psetexAsync = client.set.bind(client);
this.delAsync = client.del.bind(client);
this.scanAsync = client.scan.bind(client);
}
calculateTTL(value: IEntry) {
const now = Date.now();
if (value.expires && value.expires > now) {
return value.expires - now;
}
return -1;
}
transformKey(key: string) {
return this.prefix + '_' + key;
}
async getItem(key: string) {
const item = (await this.getAsync(this.transformKey(key))) || null;
return JSON.parse(item);
}
async setItem(key: string, value: IEntry) {
const computedKey = this.transformKey(key);
const ttl = this.calculateTTL(value);
if (ttl > 0) {
await this.psetexAsync(computedKey, JSON.stringify(value), { EX: ttl });
}
return value;
}
async removeItem(key: string) {
await this.delAsync(this.transformKey(key));
}
async scan(operation) {
let cursor = '0';
do {
const reply = await this.scanAsync(
cursor,
'MATCH',
this.transformKey('*'),
'COUNT',
this.maxScanCount,
);
cursor = reply[0];
await operation(reply[1]);
} while (cursor !== '0');
}
async clear() {
await this.scan((keys) => this.delAsync(keys));
}
async length() {
let length = 0;
await this.scan((keys) => {
length += keys.length;
});
return length;
}
async iterate(fn) {
async function runFunction(key) {
const item = (await this.getAsync(key)) || null;
const value = JSON.parse(item);
return await fn(value, key);
}
await this.scan((keys) => Promise.all(keys.map(runFunction.bind(this))));
return Promise.resolve([]);
}
}
export default RedisDefaultStore;