2021-06-03 03:36:25 +00:00
|
|
|
import {Container} from '../../di'
|
2021-08-24 04:51:53 +00:00
|
|
|
import {Awaitable, Cache, ErrorWithContext, Maybe} from '../../util'
|
2021-06-03 03:36:25 +00:00
|
|
|
import {CacheModel} from './CacheModel'
|
2021-06-02 01:59:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A cache driver whose records are stored in a database table using the CacheModel.
|
|
|
|
*/
|
|
|
|
export class ORMCache extends Cache {
|
|
|
|
public async fetch(key: string): Promise<string | undefined> {
|
2021-08-24 04:51:53 +00:00
|
|
|
return (await CacheModel.getCacheKey(key))?.cacheValue
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public async put(key: string, value: string, expires?: Date): Promise<void> {
|
|
|
|
let model = await CacheModel.findByKey<CacheModel>(key)
|
|
|
|
if ( !model ) {
|
|
|
|
model = <CacheModel> Container.getContainer().make(CacheModel)
|
|
|
|
}
|
|
|
|
|
|
|
|
model.cacheKey = key
|
|
|
|
model.cacheValue = value
|
|
|
|
model.cacheExpires = expires
|
|
|
|
|
|
|
|
await model.save()
|
|
|
|
}
|
|
|
|
|
|
|
|
public async has(key: string): Promise<boolean> {
|
2021-08-24 04:51:53 +00:00
|
|
|
return CacheModel.withCacheKey(key)
|
2021-06-02 01:59:40 +00:00
|
|
|
.exists()
|
|
|
|
}
|
|
|
|
|
|
|
|
public async drop(key: string): Promise<void> {
|
|
|
|
await CacheModel.query()
|
2021-08-24 04:51:53 +00:00
|
|
|
.whereKey(key)
|
2021-06-02 01:59:40 +00:00
|
|
|
.delete()
|
|
|
|
}
|
2021-08-24 04:51:53 +00:00
|
|
|
|
|
|
|
public async pop(key: string): Promise<string> {
|
|
|
|
return CacheModel.getConnection()
|
|
|
|
.asTransaction<string>(async () => {
|
|
|
|
const model = await CacheModel.getCacheKey(key)
|
|
|
|
if ( !model ) {
|
|
|
|
throw new ErrorWithContext('Cannot pop cache value: key does not exist.', {
|
|
|
|
key,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
await model.delete()
|
|
|
|
return model.cacheValue
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
public increment(key: string, amount = 1): Awaitable<number> {
|
|
|
|
return CacheModel.getConnection()
|
|
|
|
.asTransaction<number>(async () => {
|
|
|
|
const model = await CacheModel.getCacheKey(key)
|
|
|
|
if ( !model ) {
|
|
|
|
await this.put(key, String(amount))
|
|
|
|
return amount
|
|
|
|
}
|
|
|
|
|
|
|
|
model.cacheValue = String(parseInt(model.cacheValue, 10) + amount)
|
|
|
|
await model.save()
|
|
|
|
return parseInt(model.cacheValue, 10)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
public decrement(key: string, amount = 1): Awaitable<number> {
|
|
|
|
return CacheModel.getConnection()
|
|
|
|
.asTransaction<number>(async () => {
|
|
|
|
const model = await CacheModel.getCacheKey(key)
|
|
|
|
if ( !model ) {
|
|
|
|
await this.put(key, String(-amount))
|
|
|
|
return amount
|
|
|
|
}
|
|
|
|
|
|
|
|
model.cacheValue = String(parseInt(model.cacheValue, 10) - amount)
|
|
|
|
await model.save()
|
|
|
|
return parseInt(model.cacheValue, 10)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
public async arrayPush(key: string, value: string): Promise<void> {
|
|
|
|
await CacheModel.getConnection()
|
|
|
|
.asTransaction<void>(async () => {
|
|
|
|
const model = await CacheModel.getCacheKey(key)
|
|
|
|
if ( !model ) {
|
|
|
|
await this.put(key, JSON.stringify([value]))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
const cacheValue = JSON.parse(model.cacheValue)
|
|
|
|
if ( !Array.isArray(cacheValue) ) {
|
|
|
|
throw new ErrorWithContext('Cannot push value to non-array.', {
|
|
|
|
key,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
cacheValue.push(value)
|
|
|
|
model.cacheValue = JSON.stringify(cacheValue)
|
|
|
|
})
|
|
|
|
|
|
|
|
throw new Error('Method not implemented.')
|
|
|
|
}
|
|
|
|
|
|
|
|
public async arrayPop(key: string): Promise<Maybe<string>> {
|
|
|
|
return CacheModel.getConnection()
|
|
|
|
.asTransaction<Maybe<string>>(async () => {
|
|
|
|
const model = await CacheModel.getCacheKey(key)
|
|
|
|
if ( !model ) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
const cacheValue = JSON.parse(model.cacheValue)
|
|
|
|
if ( !Array.isArray(cacheValue) ) {
|
|
|
|
throw new ErrorWithContext('Cannot pop value from non-array.', {
|
|
|
|
key,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
const value = cacheValue.pop()
|
|
|
|
model.cacheValue = JSON.stringify(cacheValue)
|
|
|
|
await model.save()
|
|
|
|
return value
|
|
|
|
})
|
|
|
|
}
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|