You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
7.8 KiB
212 lines
7.8 KiB
import { expect } from 'chai'
|
|
import db, { DbQueryCache } from '../../src/db/index.js'
|
|
import { UserModel } from '../../src/db/models/UserModel.js'
|
|
|
|
describe('Query Cache', () => {
|
|
before(async () => {
|
|
// 确保users表存在
|
|
const exists = await db.schema.hasTable('users')
|
|
if (!exists) {
|
|
await db.schema.createTable('users', (table) => {
|
|
table.increments('id').primary()
|
|
table.string('username').unique()
|
|
table.string('email').unique()
|
|
table.string('password')
|
|
table.timestamp('created_at').defaultTo(db.fn.now())
|
|
table.timestamp('updated_at').defaultTo(db.fn.now())
|
|
})
|
|
}
|
|
|
|
// 清空缓存
|
|
DbQueryCache.clear()
|
|
})
|
|
|
|
afterEach(async () => {
|
|
// 清理测试数据
|
|
await db('users').del()
|
|
// 清空缓存
|
|
DbQueryCache.clear()
|
|
})
|
|
|
|
describe('Cache Basic Operations', () => {
|
|
it('应该正确设置和获取缓存', async () => {
|
|
const key = 'test_key'
|
|
const value = { data: 'test_value', timestamp: Date.now() }
|
|
|
|
DbQueryCache.set(key, value, 1000) // 1秒过期
|
|
const cached = DbQueryCache.get(key)
|
|
|
|
expect(cached).to.deep.equal(value)
|
|
})
|
|
|
|
it('应该正确检查缓存存在性', async () => {
|
|
const key = 'existence_test'
|
|
expect(DbQueryCache.has(key)).to.be.false
|
|
|
|
DbQueryCache.set(key, 'test_value', 1000)
|
|
expect(DbQueryCache.has(key)).to.be.true
|
|
})
|
|
|
|
it('应该正确删除缓存', async () => {
|
|
const key = 'delete_test'
|
|
DbQueryCache.set(key, 'test_value', 1000)
|
|
expect(DbQueryCache.has(key)).to.be.true
|
|
|
|
DbQueryCache.delete(key)
|
|
expect(DbQueryCache.has(key)).to.be.false
|
|
})
|
|
|
|
it('应该正确清空所有缓存', async () => {
|
|
DbQueryCache.set('key1', 'value1', 1000)
|
|
DbQueryCache.set('key2', 'value2', 1000)
|
|
|
|
const statsBefore = DbQueryCache.stats()
|
|
expect(statsBefore.valid).to.be.greaterThan(0)
|
|
|
|
DbQueryCache.clear()
|
|
|
|
const statsAfter = DbQueryCache.stats()
|
|
expect(statsAfter.valid).to.equal(0)
|
|
})
|
|
})
|
|
|
|
describe('Query Builder Cache', () => {
|
|
beforeEach(async () => {
|
|
// 创建测试用户
|
|
await UserModel.create({
|
|
username: 'cache_test',
|
|
email: 'cache_test@example.com',
|
|
password: 'password123'
|
|
})
|
|
})
|
|
|
|
it('应该正确缓存查询结果', async () => {
|
|
// 第一次查询(应该执行数据库查询)
|
|
const result1 = await db('users')
|
|
.where('username', 'cache_test')
|
|
.cache(5000) // 5秒缓存
|
|
|
|
expect(result1).to.have.length(1)
|
|
expect(result1[0].username).to.equal('cache_test')
|
|
|
|
// 修改数据库中的数据
|
|
await db('users')
|
|
.where('username', 'cache_test')
|
|
.update({ name: 'Cached User' })
|
|
|
|
// 第二次查询(应该从缓存获取,不会看到更新)
|
|
const result2 = await db('users')
|
|
.where('username', 'cache_test')
|
|
.cache(5000)
|
|
|
|
expect(result2).to.have.length(1)
|
|
expect(result2[0]).to.not.have.property('name') // 缓存的结果不会有新添加的字段
|
|
})
|
|
|
|
it('应该支持自定义缓存键', async () => {
|
|
const result = await db('users')
|
|
.where('username', 'cache_test')
|
|
.cacheAs('custom_cache_key')
|
|
.cache(5000)
|
|
|
|
// 检查自定义键是否在缓存中
|
|
expect(DbQueryCache.has('custom_cache_key')).to.be.true
|
|
})
|
|
|
|
it('应该正确使缓存失效', async () => {
|
|
// 设置缓存
|
|
await db('users')
|
|
.where('username', 'cache_test')
|
|
.cacheAs('invalidate_test')
|
|
.cache(5000)
|
|
|
|
expect(DbQueryCache.has('invalidate_test')).to.be.true
|
|
|
|
// 使缓存失效
|
|
await db('users')
|
|
.where('username', 'cache_test')
|
|
.cacheInvalidate()
|
|
|
|
// 检查缓存是否已清除
|
|
expect(DbQueryCache.has('invalidate_test')).to.be.false
|
|
})
|
|
|
|
it('应该按前缀清理缓存', async () => {
|
|
// 设置多个缓存项
|
|
await db('users').where('id', 1).cacheAs('user:1:data').cache(5000)
|
|
await db('users').where('id', 2).cacheAs('user:2:data').cache(5000)
|
|
await db('posts').where('id', 1).cacheAs('post:1:data').cache(5000)
|
|
|
|
// 检查缓存项存在
|
|
expect(DbQueryCache.has('user:1:data')).to.be.true
|
|
expect(DbQueryCache.has('user:2:data')).to.be.true
|
|
expect(DbQueryCache.has('post:1:data')).to.be.true
|
|
|
|
// 按前缀清理
|
|
await db('users').cacheInvalidateByPrefix('user:')
|
|
|
|
// 检查清理结果
|
|
expect(DbQueryCache.has('user:1:data')).to.be.false
|
|
expect(DbQueryCache.has('user:2:data')).to.be.false
|
|
expect(DbQueryCache.has('post:1:data')).to.be.true // 不受影响
|
|
})
|
|
})
|
|
|
|
describe('Cache Expiration', () => {
|
|
it('应该正确处理缓存过期', async () => {
|
|
const key = 'expire_test'
|
|
DbQueryCache.set(key, 'test_value', 10) // 10ms过期
|
|
|
|
// 立即检查应该存在
|
|
expect(DbQueryCache.has(key)).to.be.true
|
|
expect(DbQueryCache.get(key)).to.equal('test_value')
|
|
|
|
// 等待过期
|
|
await new Promise(resolve => setTimeout(resolve, 20))
|
|
|
|
// 检查应该已过期
|
|
expect(DbQueryCache.has(key)).to.be.false
|
|
expect(DbQueryCache.get(key)).to.be.undefined
|
|
})
|
|
|
|
it('应该正确清理过期缓存', async () => {
|
|
// 设置一些会过期的缓存项
|
|
DbQueryCache.set('expired_1', 'value1', 10) // 10ms过期
|
|
DbQueryCache.set('expired_2', 'value2', 10) // 10ms过期
|
|
DbQueryCache.set('valid', 'value3', 5000) // 5秒过期
|
|
|
|
// 检查初始状态
|
|
const statsBefore = DbQueryCache.stats()
|
|
expect(statsBefore.size).to.equal(3)
|
|
|
|
// 等待过期
|
|
await new Promise(resolve => setTimeout(resolve, 20))
|
|
|
|
// 清理过期缓存
|
|
const cleaned = DbQueryCache.cleanup()
|
|
expect(cleaned).to.be.greaterThanOrEqual(2)
|
|
|
|
// 检查最终状态
|
|
const statsAfter = DbQueryCache.stats()
|
|
expect(statsAfter.size).to.equal(1) // 只剩下valid项
|
|
expect(DbQueryCache.has('valid')).to.be.true
|
|
})
|
|
})
|
|
|
|
describe('Cache Statistics', () => {
|
|
it('应该正确报告缓存统计', async () => {
|
|
// 清空并设置一些测试数据
|
|
DbQueryCache.clear()
|
|
DbQueryCache.set('stat_test_1', 'value1', 5000)
|
|
DbQueryCache.set('stat_test_2', 'value2', 10) // 将过期
|
|
await new Promise(resolve => setTimeout(resolve, 20)) // 等待过期
|
|
|
|
const stats = DbQueryCache.stats()
|
|
expect(stats).to.have.property('size')
|
|
expect(stats).to.have.property('valid')
|
|
expect(stats).to.have.property('expired')
|
|
expect(stats).to.have.property('totalSize')
|
|
expect(stats).to.have.property('averageSize')
|
|
})
|
|
})
|
|
})
|