107 lines
2.3 KiB
TypeScript
107 lines
2.3 KiB
TypeScript
import {
|
|
Bulk,
|
|
connect,
|
|
Redis,
|
|
RedisConnectOptions,
|
|
RedisValue,
|
|
} from "https://deno.land/x/redis@v0.31.0/mod.ts";
|
|
import { createLogger } from "@lib/log.ts";
|
|
|
|
const REDIS_HOST = Deno.env.get("REDIS_HOST");
|
|
const REDIS_PASS = Deno.env.get("REDIS_PASS") || "";
|
|
const REDIS_PORT = Deno.env.get("REDIS_PORT");
|
|
|
|
const log = createLogger("cache");
|
|
|
|
async function createCache<T>(): Promise<Redis> {
|
|
if (REDIS_HOST) {
|
|
const conf: RedisConnectOptions = {
|
|
hostname: REDIS_HOST,
|
|
port: REDIS_PORT || 6379,
|
|
maxRetryCount: 2,
|
|
};
|
|
if (REDIS_PASS) {
|
|
conf.password = REDIS_PASS;
|
|
}
|
|
try {
|
|
const client = await connect(conf);
|
|
log.info("redis connected");
|
|
return client;
|
|
} catch (_err) {
|
|
log.info("cant connect to redis, falling back to mock");
|
|
}
|
|
}
|
|
|
|
const mockRedis = new Map<string, RedisValue>();
|
|
|
|
return {
|
|
async keys() {
|
|
return mockRedis.keys();
|
|
},
|
|
async delete(key: string) {
|
|
mockRedis.delete(key);
|
|
return key;
|
|
},
|
|
async set(key: string, value: RedisValue) {
|
|
mockRedis.set(key, value);
|
|
return value.toString();
|
|
},
|
|
async get(key: string) {
|
|
return mockRedis.get(key) as Bulk;
|
|
},
|
|
};
|
|
}
|
|
|
|
const cache = await createCache();
|
|
|
|
export async function get<T>(id: string, binary = false) {
|
|
if (binary && !(cache instanceof Map)) {
|
|
const cacheHit = await cache.sendCommand("GET", [id], {
|
|
returnUint8Arrays: true,
|
|
}) as T;
|
|
return cacheHit;
|
|
}
|
|
const cacheHit = await cache.get(id) as T;
|
|
return cacheHit;
|
|
}
|
|
export function clearAll() {
|
|
if ("flushall" in cache) {
|
|
return cache.flushall();
|
|
} else {
|
|
for (const k of cache.keys()) {
|
|
cache.delete(k);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function expire(id: string, seconds: number) {
|
|
if ("expire" in cache) {
|
|
return cache.expire(id, seconds);
|
|
}
|
|
}
|
|
|
|
type RedisOptions = {
|
|
expires?: number;
|
|
};
|
|
|
|
export function del(key: string) {
|
|
return cache.del(key);
|
|
}
|
|
|
|
export function keys(prefix: string) {
|
|
return cache.keys(prefix);
|
|
}
|
|
|
|
export async function set<T extends RedisValue>(
|
|
id: string,
|
|
content: T,
|
|
options?: RedisOptions,
|
|
) {
|
|
log.debug("storing ", { id });
|
|
const res = await cache.set(id, content);
|
|
if (options?.expires) {
|
|
await expire(id, options.expires);
|
|
}
|
|
return res;
|
|
}
|