xunch 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/lib/xunch.rb +25 -0
 - data/lib/xunch/cache/cache.rb +88 -0
 - data/lib/xunch/cache/cache_builder.rb +68 -0
 - data/lib/xunch/cache/field_object_cache.rb +120 -0
 - data/lib/xunch/cache/list_field_object_cache.rb +63 -0
 - data/lib/xunch/cache/list_object_cache.rb +59 -0
 - data/lib/xunch/cache/object_cache.rb +63 -0
 - data/lib/xunch/codec/codec.rb +31 -0
 - data/lib/xunch/codec/hash_codec.rb +98 -0
 - data/lib/xunch/codec/json_codec.rb +81 -0
 - data/lib/xunch/shard/redis.rb +270 -0
 - data/lib/xunch/shard/shard_info.rb +37 -0
 - data/lib/xunch/shard/shard_redis.rb +267 -0
 - data/lib/xunch/shard/sharded.rb +50 -0
 - data/lib/xunch/utils/exceptions.rb +11 -0
 - data/lib/xunch/utils/nginx_cache_helper.rb +52 -0
 - data/lib/xunch/utils/rb_tree.rb +634 -0
 - data/lib/xunch/utils/rb_tree_node.rb +67 -0
 - data/lib/xunch/utils/types.rb +8 -0
 - data/lib/xunch/utils/utils.rb +24 -0
 - data/test/benchmark_test.rb +68 -0
 - data/test/cache_builder_test.rb +28 -0
 - data/test/cache_object.rb +120 -0
 - data/test/consistency_hash_test.rb +31 -0
 - data/test/field_object_cache_test.rb +430 -0
 - data/test/hash_codec_test.rb +57 -0
 - data/test/json_codec_test.rb +57 -0
 - data/test/list_field_object_cache_test.rb +211 -0
 - data/test/list_object_cache_test.rb +211 -0
 - data/test/nginx_cache_helper_test.rb +45 -0
 - data/test/object_cache_test.rb +322 -0
 - data/test/rb_tree_test.rb +48 -0
 - data/test/redis_benchmark_test.rb +54 -0
 - data/test/redis_test.rb +58 -0
 - data/test/running_test.rb +212 -0
 - data/test/test.rb +176 -0
 - data/test/track_record_origin.rb +58 -0
 - metadata +125 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 11095eadd1ac6cf93128811cd1bab2d818e345b1
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 8e60835af4879fd33dfa4fe7cfc67d009548d5c2
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 6b7ca3c02e48930d5d7b551a8393c677493d3ac74ba6dc69fbf54249233ff2804d62f353e93324b62449b255b76635e39d25a8a4ba98dca17ee3a697e9d934fa
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: fed73c21df8039c4622c9ca91328f66aa5cc933f61a2230af0bd5c870804b41a1e502abeee45f875652168bcb04158947c2a2c1a6f734e183351d69f8e1041a3
         
     | 
    
        data/lib/xunch.rb
    ADDED
    
    | 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'yajl'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'date'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'bigdecimal'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'murmurhash'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'redis'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'yaml'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'xunch/utils/rb_tree'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'xunch/utils/rb_tree_node'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'xunch/utils/exceptions'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'xunch/utils/types'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'xunch/utils/utils'
         
     | 
| 
      
 12 
     | 
    
         
            +
            require 'xunch/utils/nginx_cache_helper'
         
     | 
| 
      
 13 
     | 
    
         
            +
            require 'xunch/shard/shard_info'
         
     | 
| 
      
 14 
     | 
    
         
            +
            require 'xunch/shard/sharded'
         
     | 
| 
      
 15 
     | 
    
         
            +
            require 'xunch/shard/shard_redis'
         
     | 
| 
      
 16 
     | 
    
         
            +
            require 'xunch/shard/redis'
         
     | 
| 
      
 17 
     | 
    
         
            +
            require 'xunch/codec/codec'
         
     | 
| 
      
 18 
     | 
    
         
            +
            require 'xunch/codec/json_codec'
         
     | 
| 
      
 19 
     | 
    
         
            +
            require 'xunch/codec/hash_codec'
         
     | 
| 
      
 20 
     | 
    
         
            +
            require 'xunch/cache/cache'
         
     | 
| 
      
 21 
     | 
    
         
            +
            require 'xunch/cache/object_cache'
         
     | 
| 
      
 22 
     | 
    
         
            +
            require 'xunch/cache/field_object_cache'
         
     | 
| 
      
 23 
     | 
    
         
            +
            require 'xunch/cache/list_field_object_cache'
         
     | 
| 
      
 24 
     | 
    
         
            +
            require 'xunch/cache/list_object_cache'
         
     | 
| 
      
 25 
     | 
    
         
            +
            require 'xunch/cache/cache_builder'
         
     | 
| 
         @@ -0,0 +1,88 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Xunch
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Cache
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def initialize(options, shard_infos)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @options = initialize_options(options)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @shard_redis = ShardRedis.new(@options[:regex],shard_infos)
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def evict(key)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @shard_redis.del(assembleKey(key))
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def batch_evict(keys)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  new_keys = []
         
     | 
| 
      
 15 
     | 
    
         
            +
                  keys.each { |key|
         
     | 
| 
      
 16 
     | 
    
         
            +
                    new_keys.push assembleKey(key)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  }
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @shard_redis.batch_del(new_keys)
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def destroy
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @shard_redis.destroy
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                protected 
         
     | 
| 
      
 26 
     | 
    
         
            +
                def getCacheObjectKey(value)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  key = value.send(@options[:key_field_name])
         
     | 
| 
      
 28 
     | 
    
         
            +
                  raise ArgumentError("value #{value} key field can not be nil.") unless key != nil
         
     | 
| 
      
 29 
     | 
    
         
            +
                  key
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def assembleKey(key)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  name = @options[:name]
         
     | 
| 
      
 34 
     | 
    
         
            +
                  name + "_".concat(key.to_s).concat("_").concat(@options[:version].to_s)
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def assembleTempKey(key)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  name = @options[:name]
         
     | 
| 
      
 39 
     | 
    
         
            +
                  name + "_".concat(key.to_s).concat("_").concat(@options[:version].to_s).concat("_temp")
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def initialize_options(options)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  use_options = {}
         
     | 
| 
      
 44 
     | 
    
         
            +
                  expire_time = 60 * 60 * 24 * 1000
         
     | 
| 
      
 45 
     | 
    
         
            +
                  if(options["expire_time"] != nil)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    expire_time = options["expire_time"]
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  use_options.store(:expire_time, expire_time)
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  if(options["cache_class"] != nil)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    cache_class = eval(options["cache_class"])
         
     | 
| 
      
 52 
     | 
    
         
            +
                  elsif options["type"] != CacheType::LISTOBJECT && options["type"] != CacheType::LISTFIELDOBJECT
         
     | 
| 
      
 53 
     | 
    
         
            +
                    raise ArgumentError, "cache_class is nil"
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  use_options.store(:cache_class, cache_class)
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  version = 1
         
     | 
| 
      
 58 
     | 
    
         
            +
                  if(options["version"] != nil)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    version = options["version"]
         
     | 
| 
      
 60 
     | 
    
         
            +
                    use_options.store(:version, version) 
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  if(options["name"] != nil)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    name = options["name"]
         
     | 
| 
      
 65 
     | 
    
         
            +
                    use_options.store(:name, name)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  if(options["key_field_name"] != nil)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    key_field_name = options["key_field_name"]
         
     | 
| 
      
 70 
     | 
    
         
            +
                    use_options.store(:key_field_name, key_field_name)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  if(options["timeout"] != nil)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    timeout = options["timeout"]
         
     | 
| 
      
 75 
     | 
    
         
            +
                    use_options.store(:timeout, timeout)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  regex = '[0-9]+'
         
     | 
| 
      
 79 
     | 
    
         
            +
                  if(options["regex"] != nil)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    regex = options["regex"]
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
                  use_options.store(:regex, regex)
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  return use_options
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
              end
         
     | 
| 
      
 88 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,68 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Xunch
         
     | 
| 
      
 2 
     | 
    
         
            +
              class CacheBuilder
         
     | 
| 
      
 3 
     | 
    
         
            +
                # every cache config hava attributes below:
         
     | 
| 
      
 4 
     | 
    
         
            +
                # ['type'] => the cache type, have object|field_object|list_object
         
     | 
| 
      
 5 
     | 
    
         
            +
                # ['name'] => the cache name, used for redis key prefix
         
     | 
| 
      
 6 
     | 
    
         
            +
                # ['version'] => the cache version, maybe you change your cache object format and you will change a version of the cache
         
     | 
| 
      
 7 
     | 
    
         
            +
                # ['expire_time'] => cache expire time for every key in millisecond
         
     | 
| 
      
 8 
     | 
    
         
            +
                # ['cache_class'] => which type of object you cache, this will help us to encode/decode your object
         
     | 
| 
      
 9 
     | 
    
         
            +
                # ['key_field_name'] => define which field in the object we used for redis key
         
     | 
| 
      
 10 
     | 
    
         
            +
                # ['regex'] => a regex string which used for match consistency hash key
         
     | 
| 
      
 11 
     | 
    
         
            +
                # ['shard_infos'] => define which redis instance we used for caching
         
     | 
| 
      
 12 
     | 
    
         
            +
                #
         
     | 
| 
      
 13 
     | 
    
         
            +
                #
         
     | 
| 
      
 14 
     | 
    
         
            +
                def self.build(file)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  configs = YAML.load_file(file)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  shard_info_configs = configs["shard_infos"]
         
     | 
| 
      
 17 
     | 
    
         
            +
                  cache_configs = configs["caches"]
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  shards = {}
         
     | 
| 
      
 20 
     | 
    
         
            +
                  shard_info_configs.each_value  { |shard_info_config|
         
     | 
| 
      
 21 
     | 
    
         
            +
                    options = {}
         
     | 
| 
      
 22 
     | 
    
         
            +
                    shard_info_config.each { |k,v|
         
     | 
| 
      
 23 
     | 
    
         
            +
                        options[k.to_sym] = v
         
     | 
| 
      
 24 
     | 
    
         
            +
                    }
         
     | 
| 
      
 25 
     | 
    
         
            +
                    shards[options[:name]] = ShardInfo.new(options)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  }
         
     | 
| 
      
 27 
     | 
    
         
            +
                  caches = {}
         
     | 
| 
      
 28 
     | 
    
         
            +
                  lazy_caches = {}
         
     | 
| 
      
 29 
     | 
    
         
            +
                  cache_configs.each_value  { |cache_config|
         
     | 
| 
      
 30 
     | 
    
         
            +
                    shard_names = cache_config["shards"].split(",")
         
     | 
| 
      
 31 
     | 
    
         
            +
                    shard_infos = []
         
     | 
| 
      
 32 
     | 
    
         
            +
                    shard_names.each { |shard_name|
         
     | 
| 
      
 33 
     | 
    
         
            +
                      shard_infos.push(shards[shard_name])
         
     | 
| 
      
 34 
     | 
    
         
            +
                    }
         
     | 
| 
      
 35 
     | 
    
         
            +
                    case cache_config["type"]
         
     | 
| 
      
 36 
     | 
    
         
            +
                    when CacheType::OBJECT
         
     | 
| 
      
 37 
     | 
    
         
            +
                      cache = Xunch::ObjectCache.new(cache_config,shard_infos)
         
     | 
| 
      
 38 
     | 
    
         
            +
                      caches[cache_config["name"]] = cache
         
     | 
| 
      
 39 
     | 
    
         
            +
                    when CacheType::FIELDOBJECT
         
     | 
| 
      
 40 
     | 
    
         
            +
                      cache = Xunch::FieldObjectCache.new(cache_config,shard_infos)
         
     | 
| 
      
 41 
     | 
    
         
            +
                      caches[cache_config["name"]] = cache
         
     | 
| 
      
 42 
     | 
    
         
            +
                    when CacheType::LISTOBJECT
         
     | 
| 
      
 43 
     | 
    
         
            +
                      lazy_caches[cache_config] = shard_infos
         
     | 
| 
      
 44 
     | 
    
         
            +
                    when CacheType::LISTFIELDOBJECT
         
     | 
| 
      
 45 
     | 
    
         
            +
                      lazy_caches[cache_config] = shard_infos
         
     | 
| 
      
 46 
     | 
    
         
            +
                    else
         
     | 
| 
      
 47 
     | 
    
         
            +
                      raise XunchConfigError.new("Unknown cache type #{cache_config["type"]}.")
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  }
         
     | 
| 
      
 50 
     | 
    
         
            +
                  lazy_caches.each { |cache_config,shard_infos|
         
     | 
| 
      
 51 
     | 
    
         
            +
                    delegate = caches[cache_config["delegate"]]
         
     | 
| 
      
 52 
     | 
    
         
            +
                    raise XunchConfigError.new("list_cache init error, delegate does not exist.") unless delegate != nil
         
     | 
| 
      
 53 
     | 
    
         
            +
                    cache = nil
         
     | 
| 
      
 54 
     | 
    
         
            +
                    case cache_config["type"]
         
     | 
| 
      
 55 
     | 
    
         
            +
                    when CacheType::LISTOBJECT
         
     | 
| 
      
 56 
     | 
    
         
            +
                      cache = Xunch::ListObjectCache.new(cache_config,shard_infos,delegate)
         
     | 
| 
      
 57 
     | 
    
         
            +
                    when CacheType::LISTFIELDOBJECT
         
     | 
| 
      
 58 
     | 
    
         
            +
                      cache = Xunch::ListFieldObjectCache.new(cache_config,shard_infos,delegate)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    else
         
     | 
| 
      
 60 
     | 
    
         
            +
                      raise XunchConfigError.new("Unknown cache type #{cache_config["type"]}.")
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
                    
         
     | 
| 
      
 63 
     | 
    
         
            +
                    caches[cache_config["name"]] = cache
         
     | 
| 
      
 64 
     | 
    
         
            +
                  }
         
     | 
| 
      
 65 
     | 
    
         
            +
                  caches
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,120 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Xunch
         
     | 
| 
      
 2 
     | 
    
         
            +
              #
         
     | 
| 
      
 3 
     | 
    
         
            +
              #
         
     | 
| 
      
 4 
     | 
    
         
            +
              #
         
     | 
| 
      
 5 
     | 
    
         
            +
              #
         
     | 
| 
      
 6 
     | 
    
         
            +
              class FieldObjectCache < Cache
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize(options, shard_infos)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  super
         
     | 
| 
      
 10 
     | 
    
         
            +
                  fields = options['fields']
         
     | 
| 
      
 11 
     | 
    
         
            +
                  if fields == nil
         
     | 
| 
      
 12 
     | 
    
         
            +
                    raise XunchConfigError.new("fields can not be nil")
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
                  fields_array = fields.split(",")
         
     | 
| 
      
 15 
     | 
    
         
            +
                  if fields_array.length == 1 and fields_array[0].strip.empty?
         
     | 
| 
      
 16 
     | 
    
         
            +
                    raise XunchConfigError.new("fields config error")
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  formatted_fields_array = Utils.format_fields(fields_array)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @fields_array = formatted_fields_array
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @codec = HashCodec.new(@options[:cache_class],formatted_fields_array)
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def get(key)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  redis_key = assembleKey(key)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  data = @shard_redis.mapped_hget(redis_key,@fields_array)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @codec.decode(data)
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def put(value)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  putex(value,@options[:expire_time])
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def putex(value, ttl)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  if(value == nil)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    return
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  key = getCacheObjectKey(value)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  key = assembleKey(key)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  data = @codec.encode(value)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  @shard_redis.hsetall(key,data,ttl)
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                def multi_get(keys)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  redis_keys = Array.new(keys.length)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  for i in 0 .. keys.length - 1 do
         
     | 
| 
      
 46 
     | 
    
         
            +
                    redis_keys[i] = assembleKey(keys[i])
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  datas = @shard_redis.mapped_hmget(redis_keys,@fields_array)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  for i in 0 .. datas.length - 1 do
         
     | 
| 
      
 50 
     | 
    
         
            +
                    datas[i] = @codec.decode(datas[i])
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                  return datas
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                def multi_put(values)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  multi_putex(values,@options[:expire_time])
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                def multi_putex(values,ttl)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  kvs = Hash.new
         
     | 
| 
      
 61 
     | 
    
         
            +
                  values.each { | value |
         
     | 
| 
      
 62 
     | 
    
         
            +
                    if value == nil
         
     | 
| 
      
 63 
     | 
    
         
            +
                      next
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
                    key = getCacheObjectKey(value)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    redis_key = assembleKey(key);
         
     | 
| 
      
 67 
     | 
    
         
            +
                    kvs[redis_key] = @codec.encode(value);
         
     | 
| 
      
 68 
     | 
    
         
            +
                  }
         
     | 
| 
      
 69 
     | 
    
         
            +
                  @shard_redis.hmsetall(kvs, ttl);
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                def get_with_field(key, fields)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  redis_key = assembleKey(key)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  data = @shard_redis.mapped_hget(redis_key,fields)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  @codec.decode_fields(data,fields)
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                def put_with_field(value, fields)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  put_with_field_ex(value,@options[:expire_time],fields)
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                def put_with_field_ex(value, ttl, fields)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  if(value == nil)
         
     | 
| 
      
 84 
     | 
    
         
            +
                    return
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
                  key = getCacheObjectKey(value)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  key = assembleKey(key)
         
     | 
| 
      
 88 
     | 
    
         
            +
                  data = @codec.encode_fields(value,fields)
         
     | 
| 
      
 89 
     | 
    
         
            +
                  @shard_redis.hsetall(key,data,ttl)
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                def multi_put_with_field_ex(values, ttl, fields)
         
     | 
| 
      
 93 
     | 
    
         
            +
                  kvs = Hash.new
         
     | 
| 
      
 94 
     | 
    
         
            +
                  values.each { | value |
         
     | 
| 
      
 95 
     | 
    
         
            +
                    if value == nil
         
     | 
| 
      
 96 
     | 
    
         
            +
                      next
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end
         
     | 
| 
      
 98 
     | 
    
         
            +
                    key = getCacheObjectKey(value)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    key = assembleKey(key);
         
     | 
| 
      
 100 
     | 
    
         
            +
                    kvs[key] = @codec.encode_fields(value,fields);
         
     | 
| 
      
 101 
     | 
    
         
            +
                  }
         
     | 
| 
      
 102 
     | 
    
         
            +
                  @shard_redis.hmsetall(kvs, ttl);
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                def multi_put_with_field(values, fields)
         
     | 
| 
      
 106 
     | 
    
         
            +
                  multi_put_with_field_ex(values,@options[:expire_time],fields)
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                def multi_get_with_field(keys, fields)
         
     | 
| 
      
 110 
     | 
    
         
            +
                  for i in 0 .. keys.length - 1 do
         
     | 
| 
      
 111 
     | 
    
         
            +
                    keys[i] = assembleKey(keys[i])
         
     | 
| 
      
 112 
     | 
    
         
            +
                  end
         
     | 
| 
      
 113 
     | 
    
         
            +
                  datas = @shard_redis.mapped_hmget(keys,fields)
         
     | 
| 
      
 114 
     | 
    
         
            +
                  for i in 0 .. datas.length - 1 do
         
     | 
| 
      
 115 
     | 
    
         
            +
                    datas[i] = @codec.decode_fields(datas[i],fields)
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
                  return datas
         
     | 
| 
      
 118 
     | 
    
         
            +
                end
         
     | 
| 
      
 119 
     | 
    
         
            +
              end
         
     | 
| 
      
 120 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,63 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Xunch
         
     | 
| 
      
 2 
     | 
    
         
            +
              #列表缓存目前不支持并发写入,未来也不打算支持并发
         
     | 
| 
      
 3 
     | 
    
         
            +
              #主要的使用场景是发现页热门的单线程写入和并发的读取
         
     | 
| 
      
 4 
     | 
    
         
            +
              #并且提供remove接口,帮助从列表中移除已经不存在的声音,用户,专辑
         
     | 
| 
      
 5 
     | 
    
         
            +
              class ListFieldObjectCache < Cache
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(options, shard_infos, object_cache)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  super(options,shard_infos)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @delegate = object_cache
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                # 查询接口
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @key 列表的key
         
     | 
| 
      
 14 
     | 
    
         
            +
                # @page 页码
         
     | 
| 
      
 15 
     | 
    
         
            +
                # @size 页大小
         
     | 
| 
      
 16 
     | 
    
         
            +
                #
         
     | 
| 
      
 17 
     | 
    
         
            +
                def get(key, page, size)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  raise "key can not be nil." unless key != nil
         
     | 
| 
      
 19 
     | 
    
         
            +
                  raise "page must be a positive number." unless page > 0
         
     | 
| 
      
 20 
     | 
    
         
            +
                  raise "size must be a positive number and less than 100." unless page != nil or size < 100
         
     | 
| 
      
 21 
     | 
    
         
            +
                  start = (page - 1) * size;
         
     | 
| 
      
 22 
     | 
    
         
            +
                  stop = page * size - 1;
         
     | 
| 
      
 23 
     | 
    
         
            +
                  new_key = assembleKey(key)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  object_keys = @shard_redis.lrange(new_key,start,stop)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  hash = {}
         
     | 
| 
      
 26 
     | 
    
         
            +
                  hash["keys"] = object_keys
         
     | 
| 
      
 27 
     | 
    
         
            +
                  hash["values"] = @delegate.multi_get(object_keys)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  hash
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def put(key, values)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  raise "key can not be nil." unless key != nil
         
     | 
| 
      
 33 
     | 
    
         
            +
                  raise "values can not be nil." unless values != nil
         
     | 
| 
      
 34 
     | 
    
         
            +
                  sub_keys = []
         
     | 
| 
      
 35 
     | 
    
         
            +
                  values.each { | value |
         
     | 
| 
      
 36 
     | 
    
         
            +
                    raise "value in values can not be nil." unless value != nil
         
     | 
| 
      
 37 
     | 
    
         
            +
                    sub_keys.push(@delegate.getCacheObjectKey(value))
         
     | 
| 
      
 38 
     | 
    
         
            +
                  }
         
     | 
| 
      
 39 
     | 
    
         
            +
                  temp_key = assembleTempKey(key)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  new_key = assembleKey(key)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @delegate.multi_putex(values,@options[:expire_time])
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @shard_redis.lset(temp_key,new_key,sub_keys,@options[:expire_time])
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def remove(key, sub_key)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  raise "key can not be nil." unless key != nil
         
     | 
| 
      
 47 
     | 
    
         
            +
                  raise "sub_key can not be nil." unless sub_key != nil
         
     | 
| 
      
 48 
     | 
    
         
            +
                  new_key = assembleKey(key)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @shard_redis.lremove(new_key,sub_key)
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def size(key)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  raise "key can not be nil." unless key != nil
         
     | 
| 
      
 54 
     | 
    
         
            +
                  new_key = assembleKey(key)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @shard_redis.llen(new_key)
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                def delegate
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @delegate
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,59 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Xunch
         
     | 
| 
      
 2 
     | 
    
         
            +
              #列表缓存目前不支持并发写入,未来也不打算支持并发
         
     | 
| 
      
 3 
     | 
    
         
            +
              #主要的使用场景是发现页热门的单线程写入和并发的读取
         
     | 
| 
      
 4 
     | 
    
         
            +
              #并且提供remove接口,帮助从列表中移除已经不存在的声音,用户,专辑
         
     | 
| 
      
 5 
     | 
    
         
            +
              class ListObjectCache < Cache
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(options, shard_infos, object_cache)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  super(options,shard_infos)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @delegate = object_cache
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                # 查询接口
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @key 列表的key
         
     | 
| 
      
 14 
     | 
    
         
            +
                # @page 页码
         
     | 
| 
      
 15 
     | 
    
         
            +
                # @size 页大小
         
     | 
| 
      
 16 
     | 
    
         
            +
                #
         
     | 
| 
      
 17 
     | 
    
         
            +
                def get(key, page, size)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  raise "key can not be nil." unless key != nil
         
     | 
| 
      
 19 
     | 
    
         
            +
                  raise "page must be a positive number." unless page > 0
         
     | 
| 
      
 20 
     | 
    
         
            +
                  raise "size must be a positive number and less than 100." unless page != nil or size < 100
         
     | 
| 
      
 21 
     | 
    
         
            +
                  start = (page - 1) * size;
         
     | 
| 
      
 22 
     | 
    
         
            +
                  stop = page * size - 1;
         
     | 
| 
      
 23 
     | 
    
         
            +
                  new_key = assembleKey(key)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  object_keys = @shard_redis.lrange(new_key,start,stop)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  hash = {}
         
     | 
| 
      
 26 
     | 
    
         
            +
                  hash["keys"] = object_keys
         
     | 
| 
      
 27 
     | 
    
         
            +
                  hash["values"] = @delegate.multi_get(object_keys)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  hash
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def put(key, values)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  raise "key can not be nil." unless key != nil
         
     | 
| 
      
 33 
     | 
    
         
            +
                  raise "values can not be nil." unless values != nil
         
     | 
| 
      
 34 
     | 
    
         
            +
                  sub_keys = []
         
     | 
| 
      
 35 
     | 
    
         
            +
                  values.each { | value |
         
     | 
| 
      
 36 
     | 
    
         
            +
                    raise "value in values can not be nil." unless value != nil
         
     | 
| 
      
 37 
     | 
    
         
            +
                    sub_keys.push(@delegate.getCacheObjectKey(value))
         
     | 
| 
      
 38 
     | 
    
         
            +
                  }
         
     | 
| 
      
 39 
     | 
    
         
            +
                  temp_key = assembleTempKey(key)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  new_key = assembleKey(key)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @delegate.multi_putex(values,@options[:expire_time])
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @shard_redis.lset(temp_key,new_key,sub_keys,@options[:expire_time])
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def remove(key, sub_key)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  raise "key can not be nil." unless key != nil
         
     | 
| 
      
 47 
     | 
    
         
            +
                  raise "sub_key can not be nil." unless sub_key != nil
         
     | 
| 
      
 48 
     | 
    
         
            +
                  new_key = assembleKey(key)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @shard_redis.lremove(new_key,sub_key)
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def size(key)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  raise "key can not be nil." unless key != nil
         
     | 
| 
      
 54 
     | 
    
         
            +
                  new_key = assembleKey(key)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @shard_redis.llen(new_key)
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,63 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Xunch
         
     | 
| 
      
 2 
     | 
    
         
            +
              class ObjectCache < Cache
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def initialize(options, shard_infos)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  super
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @codec = JsonCodec.new(@options[:cache_class])
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def get(key)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  redis_key = assembleKey(key)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  data = @shard_redis.get(redis_key)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  if data != nil
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @codec.decode(data)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def put(value)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  putex(value,@options[:expire_time])
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def putex(value, ttl)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  if(value == nil)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    return
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  key = getCacheObjectKey(value)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  key = assembleKey(key)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  data = @codec.encode(value)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @shard_redis.set(key,data,ttl.to_s)
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def multi_get(keys)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  redis_keys = Array.new(keys.length)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  for i in 0 .. keys.length - 1 do
         
     | 
| 
      
 34 
     | 
    
         
            +
                    redis_keys[i] = assembleKey(keys[i])
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                  datas = @shard_redis.mget(redis_keys)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  for i in 0 .. datas.length - 1 do
         
     | 
| 
      
 38 
     | 
    
         
            +
                    if datas[i] != nil
         
     | 
| 
      
 39 
     | 
    
         
            +
                      datas[i] = @codec.decode(datas[i])
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                  datas
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def multi_put(values)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  multi_putex(values,@options[:expire_time])
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def multi_putex(values,ttl)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  kvs = Hash.new
         
     | 
| 
      
 51 
     | 
    
         
            +
                  values.each { | value |
         
     | 
| 
      
 52 
     | 
    
         
            +
                    if value == nil
         
     | 
| 
      
 53 
     | 
    
         
            +
                      next
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
                    key = getCacheObjectKey(value)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    key = assembleKey(key);
         
     | 
| 
      
 57 
     | 
    
         
            +
                    kvs[key] = @codec.encode(value);
         
     | 
| 
      
 58 
     | 
    
         
            +
                  }
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @shard_redis.mset(kvs, ttl);
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
            end
         
     |