sinarey_cache 0.0.1
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/sinarey_cache/fifo/cache.rb +47 -0
- data/lib/sinarey_cache/lru_redux/cache.rb +91 -0
- data/lib/sinarey_cache/lru_redux/cache19.rb +91 -0
- data/lib/sinarey_cache/version.rb +3 -0
- data/lib/sinarey_cache.rb +75 -0
- data/sinarey_cache.gemspec +23 -0
- data/test/smart_cache_test.rb +116 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 563d5fbcebdf35c800e8fb4ab1c763e71bbe95ee
|
4
|
+
data.tar.gz: 58be4d2cdac9bbd3cb380111963996dfac9d8ca4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0b131394f6b7356ae86224ce6b0d08a1f005861045a176f9f7886ada5e7e313ff438cd96b89b579e05e409efc8f62a9958fa265157e5444fb86afb336f99b97e
|
7
|
+
data.tar.gz: 1ef6d9564726f27767aae31499a2cd95144f1e2529feb3f9bf6f67a91c72f4feb166743f2425978532ff63bd44905af613b0ffeeaa4e282fd16f7c0fae4ecf69
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Sinarey
|
2
|
+
class FifoCache
|
3
|
+
|
4
|
+
def initialize(max_size)
|
5
|
+
@max_size = max_size
|
6
|
+
@data = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def max_size=(size)
|
10
|
+
raise ArgumentError.new(:max_size) if @max_size < 1
|
11
|
+
@max_size = size
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
@data[key]
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch(key)
|
19
|
+
@data[key] || yield if block_given?
|
20
|
+
end
|
21
|
+
|
22
|
+
def getset(key)
|
23
|
+
@data[key] ||= yield
|
24
|
+
end
|
25
|
+
|
26
|
+
def []=(key,val)
|
27
|
+
@data[key] = val
|
28
|
+
@data.delete(@data.first[0]) if @data.length > @max_size
|
29
|
+
val
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :store,:[]=
|
33
|
+
|
34
|
+
def member?(key)
|
35
|
+
@data.member?(key)
|
36
|
+
end
|
37
|
+
|
38
|
+
def delete(key)
|
39
|
+
@data.delete(key)
|
40
|
+
end
|
41
|
+
|
42
|
+
def clear
|
43
|
+
@data.clear
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Sinarey
|
2
|
+
class LruCache
|
3
|
+
def initialize(max_size)
|
4
|
+
@max_size = max_size
|
5
|
+
@data = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def max_size=(size)
|
9
|
+
raise ArgumentError.new(:max_size) if @max_size < 1
|
10
|
+
@max_size = size
|
11
|
+
if @max_size < @data.size
|
12
|
+
@data.keys[0..@max_size-@data.size].each do |k|
|
13
|
+
@data.delete(k)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def getset(key)
|
19
|
+
found = true
|
20
|
+
value = @data.delete(key){ found = false }
|
21
|
+
if found
|
22
|
+
@data[key] = value
|
23
|
+
else
|
24
|
+
result = @data[key] = yield
|
25
|
+
@data.delete(@data.first[0]) if @data.length > @max_size
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def fetch(key)
|
31
|
+
found = true
|
32
|
+
value = @data.delete(key){ found = false }
|
33
|
+
if found
|
34
|
+
@data[key] = value
|
35
|
+
else
|
36
|
+
yield if block_given?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def [](key)
|
41
|
+
found = true
|
42
|
+
value = @data.delete(key){ found = false }
|
43
|
+
if found
|
44
|
+
@data[key] = value
|
45
|
+
else
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def []=(key,val)
|
51
|
+
@data.delete(key)
|
52
|
+
@data[key] = val
|
53
|
+
# this may seem odd see: http://bugs.ruby-lang.org/issues/8312
|
54
|
+
@data.delete(@data.first[0]) if @data.length > @max_size
|
55
|
+
val
|
56
|
+
end
|
57
|
+
|
58
|
+
def each
|
59
|
+
array = @data.to_a
|
60
|
+
array.reverse!.each do |pair|
|
61
|
+
yield pair
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# used further up the chain, non thread safe each
|
66
|
+
alias_method :each_unsafe, :each
|
67
|
+
|
68
|
+
def to_a
|
69
|
+
array = @data.to_a
|
70
|
+
array.reverse!
|
71
|
+
end
|
72
|
+
|
73
|
+
def delete(k)
|
74
|
+
@data.delete(k)
|
75
|
+
end
|
76
|
+
|
77
|
+
def clear
|
78
|
+
@data.clear
|
79
|
+
end
|
80
|
+
|
81
|
+
def count
|
82
|
+
@data.count
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
# for cache validation only, ensures all is sound
|
87
|
+
def valid?
|
88
|
+
true
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Sinarey
|
2
|
+
class LruCache
|
3
|
+
def initialize(max_size)
|
4
|
+
@max_size = max_size
|
5
|
+
@data = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def max_size=(size)
|
9
|
+
raise ArgumentError.new(:max_size) if @max_size < 1
|
10
|
+
@max_size = size
|
11
|
+
if @max_size < @data.size
|
12
|
+
@data.keys[0..@max_size-@data.size].each do |k|
|
13
|
+
@data.delete(k)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def getset(key)
|
19
|
+
found = true
|
20
|
+
value = @data.delete(key){ found = false }
|
21
|
+
if found
|
22
|
+
@data[key] = value
|
23
|
+
else
|
24
|
+
result = @data[key] = yield
|
25
|
+
@data.delete(@data.first[0]) if @data.length > @max_size
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def fetch(key)
|
31
|
+
found = true
|
32
|
+
value = @data.delete(key){ found = false }
|
33
|
+
if found
|
34
|
+
@data[key] = value
|
35
|
+
else
|
36
|
+
yield if block_given?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def [](key)
|
41
|
+
found = true
|
42
|
+
value = @data.delete(key){ found = false }
|
43
|
+
if found
|
44
|
+
@data[key] = value
|
45
|
+
else
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def []=(key,val)
|
51
|
+
@data.delete(key)
|
52
|
+
@data[key] = val
|
53
|
+
# this may seem odd see: http://bugs.ruby-lang.org/issues/8312
|
54
|
+
@data.delete(@data.first[0]) if @data.length > @max_size
|
55
|
+
val
|
56
|
+
end
|
57
|
+
|
58
|
+
def each
|
59
|
+
array = @data.to_a
|
60
|
+
array.reverse!.each do |pair|
|
61
|
+
yield pair
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# used further up the chain, non thread safe each
|
66
|
+
alias_method :each_unsafe, :each
|
67
|
+
|
68
|
+
def to_a
|
69
|
+
array = @data.to_a
|
70
|
+
array.reverse!
|
71
|
+
end
|
72
|
+
|
73
|
+
def delete(k)
|
74
|
+
@data.delete(k)
|
75
|
+
end
|
76
|
+
|
77
|
+
def clear
|
78
|
+
@data.clear
|
79
|
+
end
|
80
|
+
|
81
|
+
def count
|
82
|
+
@data.count
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
# for cache validation only, ensures all is sound
|
87
|
+
def valid?
|
88
|
+
true
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
require 'sinarey_cache/fifo/cache'
|
3
|
+
|
4
|
+
major,minor = RUBY_VERSION.split(".").map{|a| a.to_i}
|
5
|
+
if major > 1 || (major == 1 && minor > 8)
|
6
|
+
require "sinarey_cache/lru_redux/cache19"
|
7
|
+
else
|
8
|
+
require "sinarey_cache/lru_redux/cache"
|
9
|
+
end
|
10
|
+
|
11
|
+
module Sinarey
|
12
|
+
class SmartCache
|
13
|
+
|
14
|
+
def initialize(data_size,fifo_size)
|
15
|
+
@fifo = Sinarey::FifoCache.new(fifo_size)
|
16
|
+
@data = Sinarey::LruCache.new(data_size)
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](key)
|
20
|
+
@data[key]
|
21
|
+
end
|
22
|
+
|
23
|
+
def fetch(key)
|
24
|
+
if cache = @data[key]
|
25
|
+
return cache
|
26
|
+
else
|
27
|
+
yield if block_given?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def []=(key,val,options={})
|
32
|
+
return @data[key] = val if options[:force]
|
33
|
+
val,version = val,options[:uuid]
|
34
|
+
if @fifo.member?(key)
|
35
|
+
if version.nil?
|
36
|
+
@data[key] = val
|
37
|
+
elsif version!= @fifo[key]
|
38
|
+
@fifo[key] = version
|
39
|
+
@data[key] = val
|
40
|
+
end
|
41
|
+
else
|
42
|
+
@fifo[key] = version
|
43
|
+
end
|
44
|
+
val
|
45
|
+
end
|
46
|
+
|
47
|
+
alias_method :store,:[]=
|
48
|
+
|
49
|
+
def getset(key,options={})
|
50
|
+
if cache = @data[key]
|
51
|
+
return cache
|
52
|
+
else
|
53
|
+
store(key,yield,options) if block_given?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def count
|
58
|
+
@data.count
|
59
|
+
end
|
60
|
+
|
61
|
+
def delete(k)
|
62
|
+
@fifo.delete(k)
|
63
|
+
@data.delete(k)
|
64
|
+
end
|
65
|
+
|
66
|
+
def clear
|
67
|
+
@fifo.clear
|
68
|
+
@data.clear
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sinarey_cache/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sinarey_cache"
|
8
|
+
spec.version = SinareyCache::VERSION
|
9
|
+
spec.authors = ["Jeffrey"]
|
10
|
+
spec.email = ["jeffrey6052@163.com"]
|
11
|
+
spec.description = "smart and fast cache"
|
12
|
+
spec.summary = ""
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = ['lib/sinarey_cache/fifo/cache.rb',
|
17
|
+
'lib/sinarey_cache/lru_redux/cache.rb',
|
18
|
+
'lib/sinarey_cache/lru_redux/cache19.rb',
|
19
|
+
'lib/sinarey_cache/version.rb',
|
20
|
+
'lib/sinarey_cache.rb',
|
21
|
+
'test/smart_cache_test.rb',
|
22
|
+
'sinarey_cache.gemspec']
|
23
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
|
2
|
+
$:.unshift File.expand_path("../lib", __dir__)
|
3
|
+
|
4
|
+
require 'sinarey_cache'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
|
7
|
+
ObjectCache = Sinarey::SmartCache.new(100,100)
|
8
|
+
|
9
|
+
# MARK 实例方法 []= , store , [], fetch , getset , delete , count , clear
|
10
|
+
|
11
|
+
class SmartCacheTest < MiniTest::Unit::TestCase
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@object = {id:1, msg:'this is the object for test', name:'object'}
|
15
|
+
@object1 = {id:2, msg:'I need some more object for test', name:'object1'}
|
16
|
+
@object2 = {id:3, msg:'hahahahaha', name:'object2'}
|
17
|
+
end
|
18
|
+
|
19
|
+
#基本测试 [] , []= , store , fetch, count , delete , clear
|
20
|
+
def test_basic
|
21
|
+
|
22
|
+
obj_id = @object[:id]
|
23
|
+
|
24
|
+
#第一次不会缓存,只在FIFO队列里留下标记
|
25
|
+
ObjectCache[obj_id] = @object
|
26
|
+
assert_equal ObjectCache[obj_id], nil
|
27
|
+
assert_equal ObjectCache.fetch(obj_id), nil
|
28
|
+
assert_equal ObjectCache.count, 0
|
29
|
+
|
30
|
+
#fetch方法,获取不到内容的时候会取后面block返回值
|
31
|
+
#这个方法不会缓存block返回值,另一个getset方法会,并且遵循缓存规则。
|
32
|
+
assert_equal ObjectCache.fetch(obj_id), nil
|
33
|
+
assert_equal ObjectCache.fetch(obj_id){123}, 123
|
34
|
+
assert_equal ObjectCache.count, 0
|
35
|
+
|
36
|
+
#第二次会缓存,因为FIFO队列里已经有标记
|
37
|
+
ObjectCache[obj_id] = @object
|
38
|
+
assert_equal ObjectCache[obj_id], @object
|
39
|
+
assert_equal ObjectCache.fetch(obj_id), @object
|
40
|
+
assert_equal ObjectCache.count, 1
|
41
|
+
|
42
|
+
#fetch方法,有缓存的情况下返回缓存内容
|
43
|
+
assert_equal ObjectCache.fetch(obj_id), @object
|
44
|
+
assert_equal ObjectCache.fetch(obj_id){123}, @object
|
45
|
+
assert_equal ObjectCache.count, 1
|
46
|
+
|
47
|
+
#delete方法 同时清除FIFO队列里的标记
|
48
|
+
ObjectCache.delete(obj_id)
|
49
|
+
assert_equal ObjectCache[obj_id], nil
|
50
|
+
assert_equal ObjectCache.fetch(obj_id), nil
|
51
|
+
|
52
|
+
#按照缓存规则 这一次缓存不会真正建立
|
53
|
+
ObjectCache[obj_id] = @object
|
54
|
+
assert_equal ObjectCache[obj_id], nil
|
55
|
+
assert_equal ObjectCache.fetch(obj_id), nil
|
56
|
+
|
57
|
+
#第二次缓存顺利建立
|
58
|
+
ObjectCache[obj_id] = @object
|
59
|
+
assert_equal ObjectCache[obj_id], @object
|
60
|
+
assert_equal ObjectCache.fetch(obj_id), @object
|
61
|
+
|
62
|
+
#store方法等价于[]=方法
|
63
|
+
ObjectCache.store @object1[:id], @object1
|
64
|
+
#按照规则,需要连写两遍,才能成功缓存
|
65
|
+
ObjectCache.store @object1[:id], @object1
|
66
|
+
|
67
|
+
#调用store方法,可以添加force选项,绕过规则,强制缓存
|
68
|
+
ObjectCache.store @object2[:id], @object2, force:true
|
69
|
+
|
70
|
+
#现在应该有3个缓存
|
71
|
+
assert_equal ObjectCache.count, 3
|
72
|
+
|
73
|
+
#测试clear方法,清空所有缓存和FIFO标记
|
74
|
+
ObjectCache.clear
|
75
|
+
assert_equal ObjectCache.count, 0
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
#测试getset方法 这个方法类似于fetch方法,不同的是,会缓存block的返回值,遵循缓存规则
|
80
|
+
def test_getset_method
|
81
|
+
obj_id = @object[:id]
|
82
|
+
|
83
|
+
assert_equal ObjectCache.count, 0
|
84
|
+
|
85
|
+
ObjectCache.getset(obj_id){ @object }
|
86
|
+
#按照规则这一次缓存也不会建立
|
87
|
+
assert_equal ObjectCache[obj_id], nil
|
88
|
+
|
89
|
+
ObjectCache.getset(obj_id){ @object }
|
90
|
+
#这一次建立成功
|
91
|
+
assert_equal ObjectCache[obj_id], @object
|
92
|
+
|
93
|
+
#同样可以通过force绕过规则强制缓存
|
94
|
+
ObjectCache.getset(@object1[:id],force:true){ @object1 }
|
95
|
+
assert_equal ObjectCache[@object1[:id]], @object1
|
96
|
+
|
97
|
+
ObjectCache.getset(@object2[:id],force:true){ @object2 }
|
98
|
+
assert_equal ObjectCache[@object2[:id]], @object2
|
99
|
+
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
#同一个用户不可以创建缓存
|
105
|
+
def test_uuid_options
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
#可以绕过规则强制建立缓存
|
110
|
+
def test_force_options
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sinarey_cache
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jeffrey
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-21 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: smart and fast cache
|
14
|
+
email:
|
15
|
+
- jeffrey6052@163.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/sinarey_cache/fifo/cache.rb
|
21
|
+
- lib/sinarey_cache/lru_redux/cache.rb
|
22
|
+
- lib/sinarey_cache/lru_redux/cache19.rb
|
23
|
+
- lib/sinarey_cache/version.rb
|
24
|
+
- lib/sinarey_cache.rb
|
25
|
+
- test/smart_cache_test.rb
|
26
|
+
- sinarey_cache.gemspec
|
27
|
+
homepage: ''
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubyforge_project:
|
47
|
+
rubygems_version: 2.0.14
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: ''
|
51
|
+
test_files: []
|