UNPKG

hwj-common-lib

Version:

微信小程序云开发通用模块库,支持灵活的环境配置

208 lines (178 loc) 5.13 kB
const cloud = require('wx-server-sdk') const { CLOUD_ENV, CACHE } = require('./env') const { BusinessError } = require('./error') // 初始化云开发环境 cloud.init({ env: CLOUD_ENV }) // 获取数据库实例 const db = cloud.database() class Cache { constructor(namespace) { this.namespace = namespace this.db = db.collection('cache') } // 生成缓存key _generateKey(key) { return `${this.namespace}:${key}` } // 设置缓存 async set(key, value, ttl = CACHE.TTL.MEDIUM) { const cacheKey = this._generateKey(key) const expireAt = new Date(Date.now() + ttl * 1000) // 深度处理对象,移除所有 MongoDB 内部字段 const processValue = (val) => { if (Array.isArray(val)) { return val.map(item => processValue(item)) } if (val && typeof val === 'object') { const processed = {} for (const [k, v] of Object.entries(val)) { // 跳过 MongoDB 内部字段和 null/undefined 值 if (!k.startsWith('_') && v != null) { processed[k] = processValue(v) } } return processed } return val } const cacheValue = processValue(value) try { // 先删除旧的缓存 await this.del(key) // 生成唯一的缓存文档ID const cacheId = `${cacheKey}_${Date.now()}` // 创建新的缓存文档 await this.db.add({ data: { _id: cacheId, // 显式设置文档ID cacheKey, value: cacheValue, expireAt, createTime: db.serverDate(), updateTime: db.serverDate() } }) return true } catch (error) { console.error('设置缓存失败:', error) // 如果是重复键的错误,尝试更新 if (error.errCode === -501007) { try { await this.db.where({ cacheKey }).update({ data: { value: cacheValue, expireAt, updateTime: db.serverDate() } }) return true } catch (updateError) { console.error('更新缓存失败:', updateError) throw new BusinessError(`更新缓存失败:${updateError.message}`) } } throw new BusinessError(`设置缓存失败:${error.message}`) } } // 获取缓存 async get(key) { const cacheKey = this._generateKey(key) try { const { data } = await this.db.where({ cacheKey }).get() if (!data || data.length === 0) { return null } const cache = data[0] // 检查是否过期 if (cache && new Date(cache.expireAt) > new Date()) { return cache.value } // 过期则删除 if (cache) { await this.del(key) } return null } catch (error) { console.error('获取缓存失败:', error) return null } } // 删除缓存 async del(key) { const cacheKey = this._generateKey(key) try { await this.db.where({ cacheKey }).remove() return true } catch (error) { console.error('删除缓存失败:', error) return true } } // 批量删除缓存(支持通配符) async batchDelete(pattern) { const regExp = new RegExp(`^${this.namespace}:${pattern.replace('*', '.*')}$`) try { await this.db.where({ cacheKey: db.RegExp({ regexp: regExp.source, options: 'i' }) }).remove() return true } catch (error) { console.error('批量删除缓存失败:', error) return true } } // 分布式锁 async withLock(key, callback, ttl = 10) { const lockKey = `lock:${this._generateKey(key)}` try { // 查找是否存在锁 const { data } = await this.db.where({ cacheKey: lockKey }).get() if (data && data.length > 0) { const lock = data[0] // 如果锁已过期,删除锁 if (new Date(lock.expireAt) < new Date()) { await this.db.where({ cacheKey: lockKey }).remove() } else { throw new BusinessError('资源正在被其他进程使用') } } // 创建锁 await this.db.add({ data: { cacheKey: lockKey, expireAt: new Date(Date.now() + ttl * 1000), createTime: db.serverDate() } }) // 执行回调 const value = await callback() // 释放锁 await this.db.where({ cacheKey: lockKey }).remove() return value } catch (error) { if (error.message === '资源正在被其他进程使用') { throw error } console.error('锁操作失败:', error) throw new BusinessError('获取锁失败') } } } module.exports = Cache