Code coverage report for thinkjs/lib/Lib/Driver/Cache/FileCache.js

Statements: 100% (65 / 65)      Branches: 96.43% (27 / 28)      Functions: 100% (17 / 17)      Lines: 100% (65 / 65)      Ignored: none     

All files » thinkjs/lib/Lib/Driver/Cache/ » FileCache.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 1562         2   2     59         59 59   59               91 91 91 91 91               26 26 6   20 20 20 1   19 19 18 3 3     15       1 1       20               12 12                   50 50 33 33   50 43   50 50         50 50   50 50   50                 10               4 4 3 3 3   3   1               19 19 19 19 24 24 24 18 6 6 6 6 5 3              
var fs = require('fs');
/**
 * 基于文件的缓存
 * @return {[type]} [description]
 */
module.exports = Cache(function(){
  'use strict';
  return {
    gcType: 'FileCache',
    init: function(options){
      this.options = extend({
        cache_path: C('cache_path'), //缓存目录
        cache_path_level: 2, //缓存子目录深度
        cache_file_suffix: C('cache_file_suffix') //缓存文件后缀名
      }, options);
      mkdir(this.options.cache_path);
      this.gcType += ':' + this.options.cache_path;
 
      this.super_('init', this.options);
    },
    /**
     * 存储的缓存文件
     * @param  {[type]} name [description]
     * @return {[type]}      [description]
     */
    getStoredFile: function(name){
      name = md5(this.key || name);
      var dir = name.split('').slice(0, this.options.cache_path_level).join('/');
      mkdir(this.options.cache_path + '/' + dir);
      var path = this.options.cache_path + '/' + dir + '/' + name + this.options.cache_file_suffix;
      return path;
    },
    /**
     * 获取缓存,返回promise
     * @param  {[type]} name [description]
     * @return {[type]}      [description]
     */
    getData: function(name){
      var filePath = this.getStoredFile(name);
      if (!isFile(filePath)) {
        return getPromise();
      }
      var deferred = getDefer();
      fs.readFile(filePath, {encoding: 'utf8'}, function(error, content){
        if (error || !content) {
          return deferred.resolve();
        }
        try{
          var data = JSON.parse(content);
          if (Date.now() > data.expire) {
            fs.unlink(filePath, function(){
              return deferred.resolve();
            });
          }else{
            deferred.resolve(data.data);
          }
        }catch(e){
          //异常时删除该文件
          fs.unlink(filePath, function(){
            return deferred.resolve();
          });
        }
      });
      return deferred.promise;
    },
    /**
     * 获取缓存
     * @param  {[type]} name [description]
     * @return {[type]}      [description]
     */
    get: function(name){
      return this.getData(name).then(function(data){
        return (data || {})[name];
      })
    },
    /**
     * 设置缓存值
     * @param {[type]} name    [description]
     * @param {[type]} value   [description]
     * @param {[type]} timeout [description]
     */
    setData: function(name, value, timeout){
      var key = name;
      if (isObject(name)) {
        timeout = value;
        key = Object.keys(name)[0];
      }
      if (timeout === undefined) {
        timeout = this.options.timeout;
      }
      var filePath = this.getStoredFile(key);
      var data = {
        data: isObject(name) ? name : getObject(name, value),
        expire: Date.now() + timeout * 1000,
        timeout: timeout
      };
      var deferred = getDefer();
      fs.writeFile(filePath, JSON.stringify(data), function(){
        //修改缓存文件权限,避免不同账号下启动时可能会出现无权限的问题
        chmod(filePath);
        deferred.resolve();
      })
      return deferred.promise;
    },
    /**
     * 设置缓存
     * @param {[type]} name   [description]
     * @param {[type]} value  [description]
     * @param {[type]} expire [description]
     */
    set: function(name, value, timeout){
      return this.setData(name, value, timeout);
    },
    /**
     * 删除缓存
     * @param  {[type]} name [description]
     * @return {[type]}      [description]
     */
    rm: function(name){
      var filePath = this.getStoredFile(name);
      if (isFile(filePath)) {
        var deferred = getDefer();
        fs.unlink(filePath, function(){
          deferred.resolve();
        })
        return deferred.promise;
      }
      return getPromise();
    },
    /**
     * gc
     * @param  {[type]} now [description]
     * @return {[type]}     [description]
     */
    gc: function(now, path){
      path = path || this.options.cache_path;
      var self = this;
      var files = fs.readdirSync(path);
      files.forEach(function(item){
        var filePath = path + '/' + item;
        var stat = fs.statSync(filePath);
        if (stat.isDirectory()) {
          self.gc(now, filePath);
        }else Eif (stat.isFile()) {
          var data = getFileContent(filePath);
          try{
            data = JSON.parse(data);
            if (now > data.expire) {
              fs.unlink(filePath, function(){});
            }
          }catch(e){}
        }
      });
    }
  };
});