UNPKG

@zenweb/cache

Version:
88 lines (87 loc) 2.37 kB
import { zenwebDebug } from '@zenweb/core'; import crypto from 'node:crypto'; export const debug = zenwebDebug('cache'); /** * Promise 等待 * @param ms 毫秒 * @returns */ export function sleep(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } /** * 执行 Redis Lua 脚本 * @param redis Redis 实例 * @param hash 脚本 sha1 hash * @param script 脚本代码 * @param keys 输入键 * @param values 输入值 * @returns 执行结果 */ export async function runRedisScript(redis, hash, script, keys, values = []) { try { const result = await redis.evalsha(hash, keys.length, ...keys, ...values); return result; } catch (err) { if (err instanceof Error && err.message.includes('NOSCRIPT')) { debug('runRedisScript: NOSCRIPT'); // 缺少预设脚本,设置 const result = await redis.eval(script, keys.length, ...keys, ...values); return result; } throw err; } } /** * 将一个嵌套对象转换为平面字符串结构 */ function plainify(obj) { if (Array.isArray(obj)) { return obj.map(plainify).join(','); } if (obj instanceof Date) { return obj.toJSON(); } if (Buffer.isBuffer(obj)) { return obj.toString('utf-8'); } if (obj && typeof obj === 'object') { return Object.keys(obj).sort().map(k => `${k}=${plainify(obj[k])}`).join('&'); } return String(obj); } /** * 对象使用 `plainify` 处理,如果对象过长则使用摘要 * @param obj * @returns */ function plainifyOrHash(obj) { let p = plainify(obj); if (Buffer.byteLength(p, 'utf8') > 16) { // 参数太长只取摘要 p = crypto.createHash('sha1').update(p, 'utf8').digest().subarray(0, 10).toString('base64url'); } return p; } /** * 生成一个参数缓存key * - 多个元素用 : 连接 */ export function cacheKey(...key) { return key.map(i => { if (i === null) return 'N'; switch (typeof i) { case 'string': return i; case 'number': return String(i); case 'boolean': return i ? 'T' : 'F'; case 'undefined': return ''; } if (i instanceof Date) return i.toJSON(); return plainifyOrHash(i); }).join(':'); }