basiccache 0.0.15 → 0.0.20
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 +4 -4
- data/.gitignore +3 -1
- data/.rspec +2 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +14 -0
- data/Gemfile.lock +71 -0
- data/README.md +5 -1
- data/Rakefile +9 -7
- data/basiccache.gemspec +9 -4
- data/lib/basiccache.rb +13 -113
- data/lib/caches/cache.rb +56 -0
- data/lib/caches/timecache.rb +56 -0
- data/lib/version.rb +6 -0
- data/spec/basiccache_spec.rb +27 -0
- data/spec/caches/cache_spec.rb +74 -0
- data/spec/caches/timecache_spec.rb +93 -0
- data/spec/spec_helper.rb +10 -0
- data/vendor/cache/ast-1.1.0.gem +0 -0
- data/vendor/cache/coveralls-0.7.0.gem +0 -0
- data/vendor/cache/diff-lcs-1.2.5.gem +0 -0
- data/vendor/cache/docile-1.1.0.gem +0 -0
- data/vendor/cache/fuubar-1.2.1.gem +0 -0
- data/vendor/cache/hashr-0.0.22.gem +0 -0
- data/vendor/cache/mime-types-2.0.gem +0 -0
- data/vendor/cache/multi_json-1.8.2.gem +0 -0
- data/vendor/cache/parser-2.1.0.pre1.gem +0 -0
- data/vendor/cache/powerpack-0.0.9.gem +0 -0
- data/vendor/cache/rainbow-1.1.4.gem +0 -0
- data/vendor/cache/rake-10.1.0.gem +0 -0
- data/vendor/cache/rest-client-1.6.7.gem +0 -0
- data/vendor/cache/rspec-2.14.1.gem +0 -0
- data/vendor/cache/rspec-core-2.14.7.gem +0 -0
- data/vendor/cache/rspec-expectations-2.14.4.gem +0 -0
- data/vendor/cache/rspec-instafail-0.2.4.gem +0 -0
- data/vendor/cache/rspec-mocks-2.14.4.gem +0 -0
- data/vendor/cache/rubocop-0.15.0.gem +0 -0
- data/vendor/cache/ruby-progressbar-1.2.0.gem +0 -0
- data/vendor/cache/simplecov-0.8.2.gem +0 -0
- data/vendor/cache/simplecov-html-0.8.0.gem +0 -0
- data/vendor/cache/slop-3.4.7.gem +0 -0
- data/vendor/cache/term-ansicolor-1.2.2.gem +0 -0
- data/vendor/cache/thor-0.18.1.gem +0 -0
- data/vendor/cache/tins-0.13.1.gem +0 -0
- data/vendor/cache/travis-lint-1.7.0.gem +0 -0
- metadata +128 -6
- data/test/test_cache.rb +0 -45
- data/test/test_timecache.rb +0 -53
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6d26e28611809e1c17212440faaaa94319aacaf8
|
|
4
|
+
data.tar.gz: 21891b1bb95fe52cf1649116cf9a74242fd198ab
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d5fc7054bb18c0d22fd596b4b2feb07871393bf0dbadb44c25b5ab3c055e8782f21ee19e56a68435993060c688d1f587e4bff40c0c235b40b6e8f27639575abb
|
|
7
|
+
data.tar.gz: 44b0952809169aab29da48d3011a06427f2ebde3f8bb7a05b10eabd1a96594edec9c846b1cdbd61a6fdac45baa8e4cae6c0ee030985eb41fc4db9767f35feb0c
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
language: ruby
|
|
2
|
+
cache: bundler
|
|
3
|
+
rvm:
|
|
4
|
+
- ruby-head
|
|
5
|
+
- 2.0.0
|
|
6
|
+
- 1.9.3
|
|
7
|
+
notifications:
|
|
8
|
+
email: false
|
|
9
|
+
irc:
|
|
10
|
+
channels:
|
|
11
|
+
- ircs://irc.oftc.net:6697#akerl
|
|
12
|
+
channel_key: sekrit
|
|
13
|
+
template:
|
|
14
|
+
- '%{repository}/%{branch}/%{build_number}: %{message} -- %{build_url}'
|
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
basiccache (0.0.19)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: https://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
ast (1.1.0)
|
|
10
|
+
coveralls (0.7.0)
|
|
11
|
+
multi_json (~> 1.3)
|
|
12
|
+
rest-client
|
|
13
|
+
simplecov (>= 0.7)
|
|
14
|
+
term-ansicolor
|
|
15
|
+
thor
|
|
16
|
+
diff-lcs (1.2.5)
|
|
17
|
+
docile (1.1.0)
|
|
18
|
+
fuubar (1.2.1)
|
|
19
|
+
rspec (~> 2.0)
|
|
20
|
+
rspec-instafail (~> 0.2.0)
|
|
21
|
+
ruby-progressbar (~> 1.0)
|
|
22
|
+
hashr (0.0.22)
|
|
23
|
+
mime-types (2.0)
|
|
24
|
+
multi_json (1.8.2)
|
|
25
|
+
parser (2.1.0.pre1)
|
|
26
|
+
ast (~> 1.1)
|
|
27
|
+
slop (~> 3.4, >= 3.4.5)
|
|
28
|
+
powerpack (0.0.9)
|
|
29
|
+
rainbow (1.1.4)
|
|
30
|
+
rake (10.1.0)
|
|
31
|
+
rest-client (1.6.7)
|
|
32
|
+
mime-types (>= 1.16)
|
|
33
|
+
rspec (2.14.1)
|
|
34
|
+
rspec-core (~> 2.14.0)
|
|
35
|
+
rspec-expectations (~> 2.14.0)
|
|
36
|
+
rspec-mocks (~> 2.14.0)
|
|
37
|
+
rspec-core (2.14.7)
|
|
38
|
+
rspec-expectations (2.14.4)
|
|
39
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
|
40
|
+
rspec-instafail (0.2.4)
|
|
41
|
+
rspec-mocks (2.14.4)
|
|
42
|
+
rubocop (0.15.0)
|
|
43
|
+
parser (~> 2.0)
|
|
44
|
+
powerpack (~> 0.0.6)
|
|
45
|
+
rainbow (>= 1.1.4)
|
|
46
|
+
ruby-progressbar (1.2.0)
|
|
47
|
+
simplecov (0.8.2)
|
|
48
|
+
docile (~> 1.1.0)
|
|
49
|
+
multi_json
|
|
50
|
+
simplecov-html (~> 0.8.0)
|
|
51
|
+
simplecov-html (0.8.0)
|
|
52
|
+
slop (3.4.7)
|
|
53
|
+
term-ansicolor (1.2.2)
|
|
54
|
+
tins (~> 0.8)
|
|
55
|
+
thor (0.18.1)
|
|
56
|
+
tins (0.13.1)
|
|
57
|
+
travis-lint (1.7.0)
|
|
58
|
+
hashr (~> 0.0.22)
|
|
59
|
+
|
|
60
|
+
PLATFORMS
|
|
61
|
+
ruby
|
|
62
|
+
|
|
63
|
+
DEPENDENCIES
|
|
64
|
+
basiccache!
|
|
65
|
+
coveralls
|
|
66
|
+
fuubar
|
|
67
|
+
parser (~> 2.1.0.pre1)
|
|
68
|
+
rake
|
|
69
|
+
rspec
|
|
70
|
+
rubocop
|
|
71
|
+
travis-lint
|
data/README.md
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
BasicCache
|
|
2
2
|
========
|
|
3
3
|
|
|
4
|
-
[](
|
|
4
|
+
[](https://badge.fury.io/rb/basiccache)
|
|
5
|
+
[](https://gemnasium.com/akerl/basiccache)
|
|
6
|
+
[](https://codeclimate.com/github/akerl/basiccache)
|
|
7
|
+
[](https://coveralls.io/r/akerl/basiccache?branch=master)
|
|
8
|
+
[](https://travis-ci.org/akerl/basiccache)
|
|
5
9
|
|
|
6
10
|
Provides a minimal key/value caching layer
|
|
7
11
|
|
data/Rakefile
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
require
|
|
2
|
-
require '
|
|
1
|
+
require 'bundler/gem_tasks'
|
|
2
|
+
require 'rspec/core/rake_task'
|
|
3
3
|
require 'rubocop/rake_task'
|
|
4
4
|
|
|
5
5
|
desc 'Run tests'
|
|
6
|
-
|
|
7
|
-
t.libs << 'test'
|
|
8
|
-
end
|
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
9
7
|
|
|
10
8
|
desc 'Run Rubocop on the gem'
|
|
11
9
|
Rubocop::RakeTask.new(:rubocop) do |task|
|
|
12
|
-
task.patterns = ['lib
|
|
10
|
+
task.patterns = ['lib/**/*.rb', 'spec/**/*.rb']
|
|
13
11
|
task.fail_on_error = true
|
|
14
12
|
end
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
desc 'Run travis-lint on .travis.yml'
|
|
15
|
+
task :travislint do
|
|
16
|
+
fail 'There is an issue with your .travis.yml' unless system('travis-lint')
|
|
17
|
+
end
|
|
17
18
|
|
|
19
|
+
task default: [:spec, :travislint, :rubocop, :build, :install]
|
data/basiccache.gemspec
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
require File.join(Dir.pwd, 'lib/basiccache.rb')
|
|
2
|
-
|
|
3
1
|
Gem::Specification.new do |s|
|
|
4
2
|
s.name = 'basiccache'
|
|
5
|
-
s.version =
|
|
3
|
+
s.version = '0.0.20'
|
|
6
4
|
s.date = Time.now.strftime("%Y-%m-%d")
|
|
7
5
|
s.summary = 'Provides a minimal key/value caching layer'
|
|
8
6
|
s.description = "Allows an application to dynamically cache values and retrieve them later"
|
|
9
7
|
s.authors = ['Les Aker']
|
|
10
8
|
s.email = 'me@lesaker.org'
|
|
11
9
|
s.files = `git ls-files`.split
|
|
12
|
-
s.test_files = `git ls-files
|
|
10
|
+
s.test_files = `git ls-files spec/*`.split
|
|
13
11
|
s.homepage = 'https://github.com/akerl/basiccache'
|
|
14
12
|
s.license = 'MIT'
|
|
13
|
+
|
|
15
14
|
s.add_development_dependency 'rubocop'
|
|
15
|
+
s.add_development_dependency 'travis-lint'
|
|
16
|
+
s.add_development_dependency 'rake'
|
|
17
|
+
s.add_development_dependency 'coveralls'
|
|
18
|
+
s.add_development_dependency 'rspec'
|
|
19
|
+
s.add_development_dependency 'fuubar'
|
|
20
|
+
s.add_development_dependency 'parser', '~> 2.1.0.pre1'
|
|
16
21
|
end
|
|
17
22
|
|
data/lib/basiccache.rb
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
# This module provides a simple key/value cache for storing computation results
|
|
3
3
|
|
|
4
4
|
module BasicCache
|
|
5
|
-
|
|
5
|
+
# Check if we're using a version if Ruby that supports caller_locations
|
|
6
|
+
NEW_CALL = Kernel.respond_to? 'caller_locations'
|
|
6
7
|
|
|
7
8
|
class << self
|
|
8
9
|
##
|
|
@@ -11,121 +12,20 @@ module BasicCache
|
|
|
11
12
|
def new(*args)
|
|
12
13
|
self::Cache.new(*args)
|
|
13
14
|
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
##
|
|
17
|
-
# If we're using 2.0.0+, caller_locations is available and is much faster.
|
|
18
|
-
# If not, fall back to caller
|
|
19
|
-
# These methods return the name of the calling function 2 levels up
|
|
20
|
-
# This allows them to return the name of whatever called Cache.cache()
|
|
21
|
-
|
|
22
|
-
if Kernel.respond_to? 'caller_locations'
|
|
23
|
-
def self.get_caller
|
|
24
|
-
caller_locations(2, 1).first.label
|
|
25
|
-
end
|
|
26
|
-
else
|
|
27
|
-
def self.get_caller
|
|
28
|
-
caller[1][/`([^']*)'/, 1]
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
##
|
|
33
|
-
# Cache object, maintains a key/value store
|
|
34
|
-
|
|
35
|
-
class Cache
|
|
36
|
-
attr_reader :store
|
|
37
|
-
|
|
38
|
-
##
|
|
39
|
-
# Generate an empty store
|
|
40
|
-
|
|
41
|
-
def initialize
|
|
42
|
-
@store = {}
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
##
|
|
46
|
-
# Empty out either the given key or the full store
|
|
47
|
-
|
|
48
|
-
def clear!(key = nil)
|
|
49
|
-
key.nil? ? @store.clear : @store.delete(key)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
##
|
|
53
|
-
# If the key is cached, return it.
|
|
54
|
-
# If not, run the code, cache the result, and return it
|
|
55
|
-
|
|
56
|
-
def cache(key = nil, &code)
|
|
57
|
-
key ||= BasicCache.get_caller
|
|
58
|
-
@store[key.to_sym] ||= code.call
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
##
|
|
62
|
-
# Return the size of the cache
|
|
63
|
-
|
|
64
|
-
def size
|
|
65
|
-
@store.length
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
##
|
|
69
|
-
# Check if a value is cached
|
|
70
|
-
# (just a wrapper, designed to be redefined by subclasses)
|
|
71
|
-
|
|
72
|
-
def include?(key = nil)
|
|
73
|
-
key ||= BasicCache.get_caller
|
|
74
|
-
@store.include? key.to_sym
|
|
75
|
-
end
|
|
76
15
|
|
|
77
16
|
##
|
|
78
|
-
#
|
|
17
|
+
# Provide a helper method to get the calling function name
|
|
18
|
+
# If available, caller_locations is available and is much faster.
|
|
19
|
+
# If not, fall back to caller
|
|
20
|
+
# These methods return the name of the calling function 2 levels up
|
|
21
|
+
# This allows them to return the name of whatever called Cache.cache()
|
|
79
22
|
|
|
80
|
-
def
|
|
81
|
-
|
|
82
|
-
fail KeyError, 'Key not cached' unless @store.include? key.to_sym
|
|
83
|
-
@store[key.to_sym]
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
##
|
|
88
|
-
# Time-based cache object
|
|
89
|
-
|
|
90
|
-
class TimeCache < Cache
|
|
91
|
-
attr_reader :lifetime
|
|
92
|
-
|
|
93
|
-
##
|
|
94
|
-
# Generate an empty store, with a default lifetime of 60 seconds
|
|
95
|
-
|
|
96
|
-
def initialize(lifetime = 30)
|
|
97
|
-
@lifetime = lifetime
|
|
98
|
-
@cache_item = Struct.new(:stamp, :value)
|
|
99
|
-
super()
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
##
|
|
103
|
-
# If the key is cached but expired, clear it
|
|
104
|
-
|
|
105
|
-
def cache(key = nil, &code)
|
|
106
|
-
key ||= BasicCache.get_caller
|
|
107
|
-
key = key.to_sym
|
|
108
|
-
# rubocop:disable AndOr
|
|
109
|
-
unless @store.include? key and Time.now - @store[key].stamp < @lifetime
|
|
110
|
-
@store[key] = @cache_item.new(Time.now, code.call)
|
|
111
|
-
end
|
|
112
|
-
# rubocop:enable AndOr
|
|
113
|
-
@store[key].value
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
##
|
|
117
|
-
# Check if a value is cached and not expired
|
|
118
|
-
|
|
119
|
-
def include?(key = nil)
|
|
120
|
-
key ||= BasicCache.get_caller
|
|
121
|
-
key = key.to_sym
|
|
122
|
-
# rubocop:disable AndOr
|
|
123
|
-
@store.include? key and Time.now - @store[key].stamp < @lifetime
|
|
124
|
-
# rubocop:enable AndOr
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def [](key = nil)
|
|
128
|
-
super.value
|
|
23
|
+
def get_caller
|
|
24
|
+
NEW_CALL ? caller_locations(2, 1).first.label : caller[1][/`([^']*)'/, 1]
|
|
129
25
|
end
|
|
130
26
|
end
|
|
131
27
|
end
|
|
28
|
+
|
|
29
|
+
require 'version'
|
|
30
|
+
require 'caches/cache'
|
|
31
|
+
require 'caches/timecache'
|
data/lib/caches/cache.rb
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module BasicCache
|
|
2
|
+
##
|
|
3
|
+
# Cache object, maintains a key/value store
|
|
4
|
+
|
|
5
|
+
class Cache
|
|
6
|
+
attr_reader :store
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# Generate an empty store
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
@store = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Empty out either the given key or the full store
|
|
17
|
+
|
|
18
|
+
def clear!(key = nil)
|
|
19
|
+
key.nil? ? @store.clear : @store.delete(key.to_sym)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# If the key is cached, return it.
|
|
24
|
+
# If not, run the code, cache the result, and return it
|
|
25
|
+
|
|
26
|
+
def cache(key = nil, &code)
|
|
27
|
+
key ||= BasicCache.get_caller
|
|
28
|
+
@store[key.to_sym] ||= code.call
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Return the size of the cache
|
|
33
|
+
|
|
34
|
+
def size
|
|
35
|
+
@store.length
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# Check if a value is cached
|
|
40
|
+
# (just a wrapper, designed to be redefined by subclasses)
|
|
41
|
+
|
|
42
|
+
def include?(key = nil)
|
|
43
|
+
key ||= BasicCache.get_caller
|
|
44
|
+
@store.include? key.to_sym
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Retrieve cached value
|
|
49
|
+
|
|
50
|
+
def [](key = nil)
|
|
51
|
+
key ||= BasicCache.get_caller
|
|
52
|
+
fail KeyError, 'Key not cached' unless include? key.to_sym
|
|
53
|
+
@store[key.to_sym]
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module BasicCache
|
|
2
|
+
##
|
|
3
|
+
# Time-based cache object
|
|
4
|
+
|
|
5
|
+
class TimeCache < Cache
|
|
6
|
+
attr_reader :lifetime
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# Generate an empty store, with a default lifetime of 60 seconds
|
|
10
|
+
|
|
11
|
+
def initialize(lifetime = 30)
|
|
12
|
+
@lifetime = lifetime
|
|
13
|
+
@cache_item = Struct.new(:stamp, :value)
|
|
14
|
+
super()
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# If the key is cached but expired, clear it
|
|
19
|
+
|
|
20
|
+
def cache(key = nil, &code)
|
|
21
|
+
key ||= BasicCache.get_caller
|
|
22
|
+
key = key.to_sym
|
|
23
|
+
# rubocop:disable AndOr
|
|
24
|
+
unless @store.include? key and Time.now - @store[key].stamp < @lifetime
|
|
25
|
+
@store[key] = @cache_item.new(Time.now, code.call)
|
|
26
|
+
end
|
|
27
|
+
# rubocop:enable AndOr
|
|
28
|
+
@store[key].value
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Check if a value is cached and not expired
|
|
33
|
+
|
|
34
|
+
def include?(key = nil)
|
|
35
|
+
key ||= BasicCache.get_caller
|
|
36
|
+
key = key.to_sym
|
|
37
|
+
# rubocop:disable AndOr
|
|
38
|
+
@store.include? key and Time.now - @store[key].stamp < @lifetime
|
|
39
|
+
# rubocop:enable AndOr
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def [](key = nil)
|
|
43
|
+
super.value
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
##
|
|
47
|
+
# Return the size of the cache (don't include expired entries)
|
|
48
|
+
# By default, purges expired entries while iterating
|
|
49
|
+
|
|
50
|
+
def size(purge = true)
|
|
51
|
+
valid = @store.select { |k, v| Time.now - v.stamp < @lifetime }
|
|
52
|
+
@store = valid if purge
|
|
53
|
+
valid.size
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/version.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe BasicCache do
|
|
4
|
+
describe '::VERSION' do
|
|
5
|
+
it 'follows the semantic version scheme' do
|
|
6
|
+
expect(BasicCache::VERSION).to match /\d+\.\d+\.\d+/
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe '.new' do
|
|
11
|
+
it 'creates cache objects' do
|
|
12
|
+
expect(BasicCache.new).to be_an_instance_of BasicCache::Cache
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe '.get_caller' do
|
|
17
|
+
it "returns the calling function's name" do
|
|
18
|
+
expect(BasicCache.get_caller).to eql 'instance_eval'
|
|
19
|
+
end
|
|
20
|
+
it 'uses caller_locations on Ruby 2.0.0+' do
|
|
21
|
+
expect(BasicCache::NEW_CALL).to be_true if RUBY_VERSION.to_i >= 2
|
|
22
|
+
end
|
|
23
|
+
it 'uses caller on Ruby 1.x' do
|
|
24
|
+
expect(BasicCache::NEW_CALL).to be_false if RUBY_VERSION.to_i < 2
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe BasicCache::Cache do
|
|
4
|
+
let(:cache) do
|
|
5
|
+
cache = BasicCache.new
|
|
6
|
+
cache.cache('a') { 3 }
|
|
7
|
+
cache.cache('b') { 5 }
|
|
8
|
+
cache.cache { 9 }
|
|
9
|
+
cache
|
|
10
|
+
end
|
|
11
|
+
let(:names) { (0..4).map { |x| :"block (#{x} levels) in <top (required)>" } }
|
|
12
|
+
|
|
13
|
+
it 'creates a cache' do
|
|
14
|
+
expect(subject).to be_an_instance_of BasicCache::Cache
|
|
15
|
+
end
|
|
16
|
+
it 'has a hash store' do
|
|
17
|
+
expect(subject.store).to eql Hash.new
|
|
18
|
+
end
|
|
19
|
+
describe '#size' do
|
|
20
|
+
it 'shows the size of the cache' do
|
|
21
|
+
expect(cache.size).to eql 3
|
|
22
|
+
expect(BasicCache.new.size).to eql 0
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
describe '#cache' do
|
|
26
|
+
it 'caches values without a key' do
|
|
27
|
+
subject.cache { 9 }
|
|
28
|
+
expect(subject.cache { 10 }).to eql 9
|
|
29
|
+
expect(subject.include?).to be_true
|
|
30
|
+
end
|
|
31
|
+
it 'caches values with a key' do
|
|
32
|
+
subject.cache('c') { 1 }
|
|
33
|
+
expect(subject.cache('c') { 2 }).to eql 1
|
|
34
|
+
expect(subject.include? :c). to be_true
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
describe '#clear!' do
|
|
38
|
+
describe 'when given no argument' do
|
|
39
|
+
it 'clears the cache' do
|
|
40
|
+
expect(cache.size).to eql 3
|
|
41
|
+
cache.clear!
|
|
42
|
+
expect(cache.size).to eql 0
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
describe 'when given an argument' do
|
|
46
|
+
it 'removes that entry from the cache' do
|
|
47
|
+
expect(cache.size).to eql 3
|
|
48
|
+
expect(cache.clear! 'c').to be_nil
|
|
49
|
+
expect(cache.size).to eql 3
|
|
50
|
+
expect(cache.clear! 'a').to eql 3
|
|
51
|
+
expect(cache.size).to eql 2
|
|
52
|
+
expect(cache.clear! :b).to eql 5
|
|
53
|
+
expect(cache.size).to eql 1
|
|
54
|
+
expect(cache.clear! names[2]).to eql 9
|
|
55
|
+
expect(cache.size).to eql 0
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
describe '#include?' do
|
|
60
|
+
it 'checks for a value in the cache' do
|
|
61
|
+
expect(cache.include? 'a').to be_true
|
|
62
|
+
expect(cache.include? :b).to be_true
|
|
63
|
+
expect(cache.include? 'z').to be_false
|
|
64
|
+
expect(cache.include? names[2]).to be_true
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
describe '#[]' do
|
|
68
|
+
it 'returns values from the cache' do
|
|
69
|
+
expect(cache['a']).to eql 3
|
|
70
|
+
expect(cache[:b]).to eql 5
|
|
71
|
+
expect { cache[:c] }.to raise_error KeyError
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe BasicCache::TimeCache do
|
|
4
|
+
let(:cache) do
|
|
5
|
+
cache = BasicCache::TimeCache.new(1)
|
|
6
|
+
cache.cache('a') { 3 }
|
|
7
|
+
cache.cache(:b) { 5 }
|
|
8
|
+
cache.cache { 9 }
|
|
9
|
+
cache
|
|
10
|
+
end
|
|
11
|
+
let(:names) { (0..4).map { |x| :"block (#{x} levels) in <top (required)>" } }
|
|
12
|
+
|
|
13
|
+
it 'creates a cache' do
|
|
14
|
+
expect(cache).to be_an_instance_of BasicCache::TimeCache
|
|
15
|
+
end
|
|
16
|
+
it 'has a hash store' do
|
|
17
|
+
expect(subject.store).to eql Hash.new
|
|
18
|
+
end
|
|
19
|
+
it 'has a set lifetime' do
|
|
20
|
+
expect(cache.lifetime).to eq 1
|
|
21
|
+
expect(BasicCache::TimeCache.new.lifetime).to eq 30
|
|
22
|
+
end
|
|
23
|
+
describe '#size' do
|
|
24
|
+
it 'shows the size of the cache' do
|
|
25
|
+
expect(cache.size).to eql 3
|
|
26
|
+
expect(BasicCache::TimeCache.new.size).to eql 0
|
|
27
|
+
end
|
|
28
|
+
it 'does not include expired items in size' do
|
|
29
|
+
expect(cache.size).to eql 3
|
|
30
|
+
sleep 2
|
|
31
|
+
expect(cache.size).to eql 0
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
describe '#cache' do
|
|
35
|
+
it 'caches values without a key' do
|
|
36
|
+
subject.cache { 9 }
|
|
37
|
+
expect(subject.cache { 10 }).to eql 9
|
|
38
|
+
expect(subject.include?).to be_true
|
|
39
|
+
end
|
|
40
|
+
it 'caches values with a key' do
|
|
41
|
+
subject.cache('c') { 1 }
|
|
42
|
+
expect(subject.cache('c') { 2 }).to eql 1
|
|
43
|
+
expect(subject.include? :c). to be_true
|
|
44
|
+
end
|
|
45
|
+
it 'expires values after their lifetime' do
|
|
46
|
+
expect(cache.include? 'a').to be_true
|
|
47
|
+
sleep 2
|
|
48
|
+
expect(cache.include? 'a').to be_false
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
describe '#clear!' do
|
|
52
|
+
describe 'when given no argument' do
|
|
53
|
+
it 'clears the cache' do
|
|
54
|
+
expect(cache.size).to eql 3
|
|
55
|
+
cache.clear!
|
|
56
|
+
expect(cache.size).to eql 0
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
describe 'when given an argument' do
|
|
60
|
+
it 'removes that entry from the cache' do
|
|
61
|
+
expect(cache.size).to eql 3
|
|
62
|
+
cache.clear! 'c'
|
|
63
|
+
expect(cache.size).to eql 3
|
|
64
|
+
expect(cache.clear!('a')[1]).to eql 3
|
|
65
|
+
expect(cache.size).to eql 2
|
|
66
|
+
expect(cache.clear!(:b)[1]).to eql 5
|
|
67
|
+
expect(cache.size).to eql 1
|
|
68
|
+
expect(cache.clear!(names[2])[1]).to eql 9
|
|
69
|
+
expect(cache.size).to eql 0
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
describe '#include?' do
|
|
74
|
+
it 'checks for a value in the cache' do
|
|
75
|
+
expect(cache.include? 'a').to be_true
|
|
76
|
+
expect(cache.include? :b).to be_true
|
|
77
|
+
expect(cache.include? 'z').to be_false
|
|
78
|
+
expect(cache.include? names[2]).to be_true
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
describe '#[]' do
|
|
82
|
+
it 'returns values from the cache' do
|
|
83
|
+
expect(cache['a']).to eql 3
|
|
84
|
+
expect(cache[:b]).to eql 5
|
|
85
|
+
expect { cache[:c] }.to raise_error KeyError
|
|
86
|
+
end
|
|
87
|
+
it 'will not return an expired key' do
|
|
88
|
+
expect(cache['a']).to eql 3
|
|
89
|
+
sleep 2
|
|
90
|
+
expect { cache['a'] }.to raise_error KeyError
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: basiccache
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.20
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Les Aker
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2013-11-
|
|
11
|
+
date: 2013-11-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rubocop
|
|
@@ -24,6 +24,90 @@ dependencies:
|
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: travis-lint
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: coveralls
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rspec
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: fuubar
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: parser
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: 2.1.0.pre1
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: 2.1.0.pre1
|
|
27
111
|
description: Allows an application to dynamically cache values and retrieve them later
|
|
28
112
|
email: me@lesaker.org
|
|
29
113
|
executables: []
|
|
@@ -31,14 +115,50 @@ extensions: []
|
|
|
31
115
|
extra_rdoc_files: []
|
|
32
116
|
files:
|
|
33
117
|
- ".gitignore"
|
|
118
|
+
- ".rspec"
|
|
119
|
+
- ".rubocop.yml"
|
|
120
|
+
- ".travis.yml"
|
|
34
121
|
- Gemfile
|
|
122
|
+
- Gemfile.lock
|
|
35
123
|
- LICENSE
|
|
36
124
|
- README.md
|
|
37
125
|
- Rakefile
|
|
38
126
|
- basiccache.gemspec
|
|
39
127
|
- lib/basiccache.rb
|
|
40
|
-
-
|
|
41
|
-
-
|
|
128
|
+
- lib/caches/cache.rb
|
|
129
|
+
- lib/caches/timecache.rb
|
|
130
|
+
- lib/version.rb
|
|
131
|
+
- spec/basiccache_spec.rb
|
|
132
|
+
- spec/caches/cache_spec.rb
|
|
133
|
+
- spec/caches/timecache_spec.rb
|
|
134
|
+
- spec/spec_helper.rb
|
|
135
|
+
- vendor/cache/ast-1.1.0.gem
|
|
136
|
+
- vendor/cache/coveralls-0.7.0.gem
|
|
137
|
+
- vendor/cache/diff-lcs-1.2.5.gem
|
|
138
|
+
- vendor/cache/docile-1.1.0.gem
|
|
139
|
+
- vendor/cache/fuubar-1.2.1.gem
|
|
140
|
+
- vendor/cache/hashr-0.0.22.gem
|
|
141
|
+
- vendor/cache/mime-types-2.0.gem
|
|
142
|
+
- vendor/cache/multi_json-1.8.2.gem
|
|
143
|
+
- vendor/cache/parser-2.1.0.pre1.gem
|
|
144
|
+
- vendor/cache/powerpack-0.0.9.gem
|
|
145
|
+
- vendor/cache/rainbow-1.1.4.gem
|
|
146
|
+
- vendor/cache/rake-10.1.0.gem
|
|
147
|
+
- vendor/cache/rest-client-1.6.7.gem
|
|
148
|
+
- vendor/cache/rspec-2.14.1.gem
|
|
149
|
+
- vendor/cache/rspec-core-2.14.7.gem
|
|
150
|
+
- vendor/cache/rspec-expectations-2.14.4.gem
|
|
151
|
+
- vendor/cache/rspec-instafail-0.2.4.gem
|
|
152
|
+
- vendor/cache/rspec-mocks-2.14.4.gem
|
|
153
|
+
- vendor/cache/rubocop-0.15.0.gem
|
|
154
|
+
- vendor/cache/ruby-progressbar-1.2.0.gem
|
|
155
|
+
- vendor/cache/simplecov-0.8.2.gem
|
|
156
|
+
- vendor/cache/simplecov-html-0.8.0.gem
|
|
157
|
+
- vendor/cache/slop-3.4.7.gem
|
|
158
|
+
- vendor/cache/term-ansicolor-1.2.2.gem
|
|
159
|
+
- vendor/cache/thor-0.18.1.gem
|
|
160
|
+
- vendor/cache/tins-0.13.1.gem
|
|
161
|
+
- vendor/cache/travis-lint-1.7.0.gem
|
|
42
162
|
homepage: https://github.com/akerl/basiccache
|
|
43
163
|
licenses:
|
|
44
164
|
- MIT
|
|
@@ -64,5 +184,7 @@ signing_key:
|
|
|
64
184
|
specification_version: 4
|
|
65
185
|
summary: Provides a minimal key/value caching layer
|
|
66
186
|
test_files:
|
|
67
|
-
-
|
|
68
|
-
-
|
|
187
|
+
- spec/basiccache_spec.rb
|
|
188
|
+
- spec/caches/cache_spec.rb
|
|
189
|
+
- spec/caches/timecache_spec.rb
|
|
190
|
+
- spec/spec_helper.rb
|
data/test/test_cache.rb
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
require 'test/unit'
|
|
2
|
-
require 'benchmark'
|
|
3
|
-
require 'basiccache'
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
# Let's cache some stuff!
|
|
7
|
-
|
|
8
|
-
class BasicCacheTest < Test::Unit::TestCase
|
|
9
|
-
def compute(n)
|
|
10
|
-
(1..n).reduce { |a, e| a * e }
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def test_creation
|
|
14
|
-
a = BasicCache.new
|
|
15
|
-
b = BasicCache::Cache.new
|
|
16
|
-
assert_instance_of BasicCache::Cache, a
|
|
17
|
-
assert_instance_of BasicCache::Cache, b
|
|
18
|
-
assert_equal a.store, {}
|
|
19
|
-
assert_equal b.store, {}
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def test_caching
|
|
23
|
-
cache = BasicCache.new
|
|
24
|
-
cache.cache { compute(10) }
|
|
25
|
-
assert cache.store.include? :test_caching
|
|
26
|
-
assert_equal cache.store[:test_caching], 3_628_800
|
|
27
|
-
assert_equal cache.cache, 3_628_800
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def test_clearing
|
|
31
|
-
cache = BasicCache.new
|
|
32
|
-
cache.cache { compute(10) }
|
|
33
|
-
assert_equal cache.store.length, 1
|
|
34
|
-
cache.clear!
|
|
35
|
-
assert_equal cache.store.length, 0
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def test_speed_increase
|
|
39
|
-
cache = BasicCache.new
|
|
40
|
-
trials = 2.times.map do
|
|
41
|
-
Benchmark.measure { cache.cache { compute(50_000) } }.real
|
|
42
|
-
end
|
|
43
|
-
assert trials[0] > trials[1] * 1_000
|
|
44
|
-
end
|
|
45
|
-
end
|
data/test/test_timecache.rb
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
require 'test/unit'
|
|
2
|
-
require 'benchmark'
|
|
3
|
-
require 'basiccache'
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
# Lets test some timed caches!
|
|
7
|
-
|
|
8
|
-
class TimeCacheTest < Test::Unit::TestCase
|
|
9
|
-
def compute(n)
|
|
10
|
-
(1..n).reduce { |a, e| a * e }
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def test_creation
|
|
14
|
-
a = BasicCache::TimeCache.new
|
|
15
|
-
assert_instance_of BasicCache::TimeCache, a
|
|
16
|
-
assert_equal a.store, {}
|
|
17
|
-
assert_equal a.lifetime, 30
|
|
18
|
-
b = BasicCache::TimeCache.new(10)
|
|
19
|
-
assert_equal b.lifetime, 10
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def test_caching
|
|
23
|
-
cache = BasicCache::TimeCache.new
|
|
24
|
-
cache.cache { compute(10) }
|
|
25
|
-
assert cache.store.include? :test_caching
|
|
26
|
-
assert_equal cache.store[:test_caching].value, 3_628_800
|
|
27
|
-
assert_equal cache.cache, 3_628_800
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def test_clearing
|
|
31
|
-
cache = BasicCache::TimeCache.new
|
|
32
|
-
cache.cache { compute(10) }
|
|
33
|
-
assert_equal cache.store.length, 1
|
|
34
|
-
cache.clear!
|
|
35
|
-
assert_equal cache.store.length, 0
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def test_speed_increase
|
|
39
|
-
cache = BasicCache::TimeCache.new
|
|
40
|
-
trials = 2.times.map do
|
|
41
|
-
Benchmark.measure { cache.cache { compute(50_000) } }.real
|
|
42
|
-
end
|
|
43
|
-
assert trials[0] > trials[1] * 1_000
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def test_expiration
|
|
47
|
-
cache = BasicCache::TimeCache.new(3)
|
|
48
|
-
cache.cache(:test) { 100 }
|
|
49
|
-
assert cache.include? :test
|
|
50
|
-
sleep 5
|
|
51
|
-
assert cache.include?(:test) == false
|
|
52
|
-
end
|
|
53
|
-
end
|