起因
近期編碼的過程中,因框架中需集成一套基於文件的緩存服務,在google 找到了node-cache的內存方案,目前看來該方案會存在重啓/斷電導致緩存丟失的問題,所以決定自己實現一套。
npm 安裝
目前該插件已發佈至npm,大家可以直接安裝使用
npm install --save tank-cache
github 源碼
https://github.com/curry-trooper/tank-cache
使用示例
//import tank-cache
const FileCache = require("tank-cache/index")
//default savePath process.cwd()+".runtime/cache.json"
const cache = new FileCache()
//use savePath
const cache = new FileCache(".runtime/mycache.json")
//store
cache.Store("tank", "man", 1)
// or
cache.Set("tank", "man", 1)
這裏是測試用例
const describe = require('mocha').describe;
const FileCache = require("../framework/cache/FileCache")
const assert = require("assert");
describe('CacheTest', () => {
it("fileCacheTest", (done) => {
const fileCache = new FileCache()
fileCache.Store("tank","man",fileCache.TIME_ONE_SECOND)
assert.equal(fileCache.Get("tank"),"man");
fileCache.Store("tankPull","pull",fileCache.TIME_ONE_SECOND)
assert.equal(fileCache.Pull("tankPull"),"pull")
assert.equal(fileCache.Get("tankPull"),null)
fileCache.Forever("tankForever","forever")
fileCache.Add("tankAdd","add",fileCache.TIME_ONE_DAY)
assert.equal(fileCache.Get("tankPull"),null)
setTimeout(()=>{
assert.equal(fileCache.Get("tank"),"man");
assert.equal(fileCache.Get("tankForever"),"forever");
fileCache.Forget("tankForever")
},800)
setTimeout(()=>{
assert.notEqual(fileCache.Get("tank"),"man");
assert.equal(fileCache.Get("tankForever"),null);
assert.equal(fileCache.Get("tankAdd"),"add");
done();
},1100)
})
})
以下爲實現原理過程追溯
依賴
考慮到文件存儲的便利性,我們需要安裝ds插件
npm install ds
創建子類
class FileCache {
}
讀取配置
config = {
saveFile: ".runtime/cache.json"
}
data = new DS();
dirPath = ""
constructor(config) {
super();
this.config = config || this.config;
if (!path.isAbsolute(this.config.saveFile)) {
this.dirPath = path.join(process.cwd(), this.config.saveFile)
} else {
this.dirPath = this.config.saveFile
}
if (!fs.existsSync(this.dirPath)) {
fs.mkdirSync(path.dirname(this.dirPath))
// throw new Error("not found cache.saveFile:" + this.dirPath)
}
}
創建存儲方法
/**
* @private
*/
_Save() {
this.data.save(this.dirPath);
}
創建存儲方法
/**
* @private
*/
_Save() {
this.data.save(this.dirPath);
}
創建銷燬方法
/**
* @private
*/
_Nuke(key) {
delete this.data[key]
this._Save()
}
存儲
/**
* Set Store an item in the cache for a given number of seconds.
* @param key
* @param val
* @param ttl Second
* @return {*}
* @Function
*/
Store(key, val = null, ttl = 0) {
let expires = ttl === 0 ? 0 : (this._Now() + ttl * 1000);
if (val !== null) {
this.data[key] = {
expires,
val,
}
this._Save()
}
}
獲取
/**
* Get Retrieve an item from the cache by key.
* @param key
* @param defaultVal?
* @return {string|null}
* @Function
*/
Get(key, defaultVal = null) {
let val = null
let obj = this.data[key]
if (obj) {
if (obj.expires === 0 || this._Now() < obj.expires) {
val = obj.val;
} else {
val = null;
this._Nuke(key);
}
}
return val || defaultVal;
}