@daiso-tech/core
Version:
The library offers flexible, framework-agnostic solutions for modern web applications, built on adaptable components that integrate seamlessly with popular frameworks like Next Js.
124 lines (122 loc) • 4.63 kB
JavaScript
/**
* @module Cache
*/
import { TypeCacheError, } from "../../../../cache/contracts/_module-exports.js";
import { ReplyError } from "ioredis";
import { ClearIterable } from "../../../../cache/implementations/adapters/redis-cache-adapter/utilities.js";
import { RedisCacheAdapterSerde } from "../../../../cache/implementations/adapters/redis-cache-adapter/redis-cache-adapter-serde.js";
/**
* To utilize the `RedisCacheAdapter`, you must install the `"ioredis"` package and supply a {@link ISerde | `ISerde<string>`}, with adapter like {@link SuperJsonSerdeAdapter | `SuperJsonSerdeAdapter `}.
*
* IMPORT_PATH: `"@daiso-tech/core/cache/adapters"`
* @group Adapters
*/
export class RedisCacheAdapter {
static isRedisTypeError(
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
value) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return (value instanceof ReplyError &&
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
value.message.includes("ERR value is not a valid float"));
}
serde;
database;
/**
* @example
* ```ts
* import { RedisCacheAdapter } from "@daiso-tech/core/cache/adapters";
* import { Serde } from "@daiso-tech/core/serde";
* import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/adapters"
* import Redis from "ioredis";
*
* const database = new Redis("YOUR_REDIS_CONNECTION_STRING");
* const serde = new Serde(new SuperJsonSerdeAdapter());
* const cacheAdapter = new RedisCacheAdapter({
* database,
* serde,
* });
* ```
*/
constructor(settings) {
const { database, serde } = settings;
this.database = database;
this.serde = new RedisCacheAdapterSerde(serde);
this.initIncrementCommand();
}
initIncrementCommand() {
if (typeof this.database.daiso_cache_increment === "function") {
return;
}
this.database.defineCommand("daiso_cache_increment", {
numberOfKeys: 1,
lua: `
local hasKey = redis.call("exists", KEYS[1])
if hasKey == 1 then
redis.call("incrbyfloat", KEYS[1], tonumber(ARGV[1]))
end
return hasKey
`,
});
}
async get(key) {
const value = await this.database.get(key);
if (value === null) {
return null;
}
return await this.serde.deserialize(value);
}
async getAndRemove(key) {
const value = await this.database.getdel(key);
if (value === null) {
return null;
}
return this.serde.deserialize(value);
}
async add(key, value, ttl) {
if (ttl === null) {
const result = await this.database.set(key, this.serde.serialize(value), "NX");
return result === "OK";
}
const result = await this.database.set(key, this.serde.serialize(value), "PX", ttl.toMilliseconds(), "NX");
return result === "OK";
}
async put(key, value, ttl) {
if (ttl === null) {
const result = await this.database.set(key, this.serde.serialize(value), "GET");
return result !== null;
}
const result = await this.database.set(key, this.serde.serialize(value), "PX", ttl.toMilliseconds(), "GET");
return result !== null;
}
async update(key, value) {
const result = await this.database.set(key, this.serde.serialize(value), "XX");
return result === "OK";
}
async increment(key, value) {
try {
const redisResult = await this.database.daiso_cache_increment(key, this.serde.serialize(value));
const keyExists = redisResult === 1;
return keyExists;
}
catch (error) {
if (!RedisCacheAdapter.isRedisTypeError(error)) {
throw error;
}
throw new TypeCacheError(`Unable to increment or decrement none number type key "${key}"`);
}
}
async removeMany(keys) {
const deleteResult = await this.database.del(...keys);
return deleteResult > 0;
}
async removeAll() {
await this.database.flushdb();
}
async removeByKeyPrefix(prefix) {
for await (const _ of new ClearIterable(this.database, prefix)) {
/* Empty */
}
}
}
//# sourceMappingURL=redis-cache-adapter.js.map