Files
cnpmcore/app/common/adapter/CacheAdapter.ts
fengmk2 4427a4fca5 feat: use egg v4 (#747)
BREAKING CHANGE: only support egg >= 4.0.0

the first app on egg v4

https://github.com/eggjs/egg/issues/3644
2025-02-09 15:43:24 +08:00

80 lines
2.0 KiB
TypeScript

import {
SingletonProto,
AccessLevel,
Inject,
} from '@eggjs/tegg';
// FIXME: @eggjs/redis should use ioredis v5
// https://github.com/eggjs/redis/issues/35
import type { Redis } from 'ioredis';
const ONE_DAY = 3600 * 24;
@SingletonProto({
accessLevel: AccessLevel.PUBLIC,
})
export class CacheAdapter {
@Inject()
private readonly redis: Redis; // 由 redis 插件引入
async setBytes(key: string, bytes: Buffer) {
await this.redis.setex(key, ONE_DAY, bytes);
}
async getBytes(key: string) {
return await this.redis.getBuffer(key);
}
async set(key: string, text: string) {
await this.redis.setex(key, ONE_DAY, text);
}
async get(key: string) {
return await this.redis.get(key);
}
async delete(key: string) {
await this.redis.del(key);
}
async lock(key: string, seconds: number) {
const lockName = this.getLockName(key);
const existsTimestamp = await this.redis.get(lockName);
if (existsTimestamp) {
if (Date.now() - parseInt(existsTimestamp) < seconds * 1000) {
return null;
}
// lock timeout, delete it
await this.redis.del(lockName);
}
const timestamp = `${Date.now() + seconds * 1000}`;
const code = await this.redis.setnx(lockName, timestamp);
// setnx fail, lock fail
if (code === 0) return null;
// expire
await this.redis.expire(lockName, seconds);
return timestamp;
}
async unlock(key: string, lockTimestamp: string) {
const lockName = this.getLockName(key);
const existsTimestamp = await this.redis.get(lockName);
if (!existsTimestamp || lockTimestamp !== existsTimestamp) return;
await this.redis.del(lockName);
}
async usingLock(key: string, seconds: number, func: () => Promise<void>) {
const lockTimestamp = await this.lock(key, seconds);
if (!lockTimestamp) return false;
try {
await func();
} finally {
await this.unlock(key, lockTimestamp);
}
return true;
}
private getLockName(key: string) {
return `CNPMCORE_L_${key}`;
}
}