nodejs 基於文件系統的緩存實現

起因

近期編碼的過程中,因框架中需集成一套基於文件的緩存服務,在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;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章