ruby-blockcache 0.2
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.
- data/LICENSE +21 -0
- data/README.md +44 -0
- data/lib/blockcache.rb +120 -0
- metadata +49 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2010, Matthew Scharley
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
* Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
* Neither the name of the copyright holder, BlockCache nor the
|
9
|
+
names of its contributors may be used to endorse or promote products
|
10
|
+
derived from this software without specific prior written permission.
|
11
|
+
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
13
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
14
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
15
|
+
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
16
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
17
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
18
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
19
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
20
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
21
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# BlockCache
|
2
|
+
|
3
|
+
by Matthew Scharley
|
4
|
+
http://github.com/mscharley/ruby-blockcache
|
5
|
+
|
6
|
+
## Overview
|
7
|
+
|
8
|
+
> In computer science, a cache is a component that improves performance
|
9
|
+
> by transparently storing data such that future requests for that
|
10
|
+
> data can be served faster.
|
11
|
+
>
|
12
|
+
> -- [Cache at Wikipedia](http://en.wikipedia.org/wiki/Cache)
|
13
|
+
|
14
|
+
Typical caches do this by allowing you to store data in them, along with
|
15
|
+
a time limit to describe how long this data is valid for. You then need
|
16
|
+
to check if the data is available, and if not, regenerate it and store
|
17
|
+
it again, ready for next time.
|
18
|
+
|
19
|
+
BlockCache eliminates all this. You define your cache, describe the
|
20
|
+
elements it contains, and then you never have to worry about making
|
21
|
+
sure you have fresh data again. Of course, if you need to ensure that
|
22
|
+
you are getting clean, uncached data, you can do that too.
|
23
|
+
|
24
|
+
## Example Usage
|
25
|
+
|
26
|
+
require 'blockcache'
|
27
|
+
|
28
|
+
cache = BlockCache.new
|
29
|
+
cache.add('name', 10) do
|
30
|
+
puts "Hello, what is your name?"
|
31
|
+
STDIN.gets.strip
|
32
|
+
end
|
33
|
+
|
34
|
+
for i in [1,2]
|
35
|
+
for j in [1,3]
|
36
|
+
puts "Hello " + cache['name'] + "!"
|
37
|
+
end
|
38
|
+
cache.refresh
|
39
|
+
end
|
40
|
+
|
41
|
+
In the example above, you get asked for your name, then it says
|
42
|
+
hello to you three times. Note, each time is using the exact same
|
43
|
+
code. The program then tells the cache that it wants fresh data,
|
44
|
+
and repeats the process.
|
data/lib/blockcache.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
|
2
|
+
# This is a class used to cache data from the repository, so that it
|
3
|
+
# needn't be queried over and over. Use a timeout of a few seconds to
|
4
|
+
# prevent repeated queries in the same operation, but preserve the
|
5
|
+
# ability to retrieve up to date data.
|
6
|
+
#
|
7
|
+
# You can call #refresh to reset all the timeouts manually if you
|
8
|
+
# need to guarantee fresh data
|
9
|
+
#
|
10
|
+
# Example usage:
|
11
|
+
#
|
12
|
+
# def cache
|
13
|
+
# @cache ||= begin
|
14
|
+
# c = BlockCache.new
|
15
|
+
# c.add("test", 10) { "Hello world!" }
|
16
|
+
# # This block always returns the same thing, so never refresh it
|
17
|
+
# c.add("test2") { |name| "Hello #{name}" }
|
18
|
+
# c
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# cache["test2", "Matthew"] # "Hello Matthew"
|
23
|
+
|
24
|
+
class BlockCache
|
25
|
+
|
26
|
+
#attr_reader :values, :accessed
|
27
|
+
|
28
|
+
def initialize(default=nil)
|
29
|
+
@default_value = default
|
30
|
+
@blocks = {}
|
31
|
+
@timeouts = {}
|
32
|
+
@accessed = {}
|
33
|
+
@values = {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def add(name, timeout, &block)
|
37
|
+
@blocks[name] = block
|
38
|
+
@timeouts[name] = timeout
|
39
|
+
end
|
40
|
+
|
41
|
+
def [](name, *args)
|
42
|
+
return @default_value if not @blocks.keys.include?(name)
|
43
|
+
|
44
|
+
atime = get_accessed(@accessed, [name, *args])
|
45
|
+
ctime = Time.now
|
46
|
+
|
47
|
+
if ((not @timeouts[name].nil?) or (not value_exist?(@values, [name, *args]))) and ctime - atime > (@timeouts[name] || 0)
|
48
|
+
begin
|
49
|
+
set_value(@values, @blocks[name].call(*args), [name, *args])
|
50
|
+
rescue
|
51
|
+
# dump errors to the console, but otherwise, keep on trucking
|
52
|
+
puts $!.message
|
53
|
+
puts $!.backtrace
|
54
|
+
set_value(@values, @default_value, [name, *args])
|
55
|
+
end
|
56
|
+
|
57
|
+
set_accessed(@accessed, ctime, [name, *args])
|
58
|
+
end
|
59
|
+
|
60
|
+
get_value(@values, [name, *args])
|
61
|
+
end
|
62
|
+
|
63
|
+
def refresh(times=@accessed)
|
64
|
+
times.each do |k, v|
|
65
|
+
if v.respond_to? '[]'
|
66
|
+
refresh v
|
67
|
+
else
|
68
|
+
times[k] = Time.at(0)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def value_exist?(values, path)
|
76
|
+
while path.length > 1
|
77
|
+
curr = path.shift
|
78
|
+
values = values[curr]
|
79
|
+
return false if not values.respond_to? '[]'
|
80
|
+
end
|
81
|
+
|
82
|
+
return values.keys.include?(path[0])
|
83
|
+
end
|
84
|
+
|
85
|
+
def get_value(values, path)
|
86
|
+
get_from_path(values, path, @default_value)
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_accessed(times, path)
|
90
|
+
get_from_path(times, path, Time.at(0))
|
91
|
+
end
|
92
|
+
|
93
|
+
def get_from_path(hash, path, default)
|
94
|
+
while path.length > 1
|
95
|
+
curr = path.shift
|
96
|
+
hash = hash[curr]
|
97
|
+
return default if not hash.respond_to? '[]'
|
98
|
+
end
|
99
|
+
|
100
|
+
return hash[path[0]] || default
|
101
|
+
end
|
102
|
+
|
103
|
+
def set_value(values, value, path)
|
104
|
+
set_from_path(values, value, path)
|
105
|
+
end
|
106
|
+
|
107
|
+
def set_accessed(times, time, path)
|
108
|
+
set_from_path(times, time, path)
|
109
|
+
end
|
110
|
+
|
111
|
+
def set_from_path(hash, value, path)
|
112
|
+
while path.length > 1
|
113
|
+
curr = path.shift
|
114
|
+
hash[curr] ||= {}
|
115
|
+
hash = hash[curr]
|
116
|
+
end
|
117
|
+
|
118
|
+
hash[path[0]] = value
|
119
|
+
end
|
120
|
+
end
|
metadata
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-blockcache
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.2'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Matt Scharley
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-09-10 00:00:00.000000000 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
description: ''
|
16
|
+
email: []
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/blockcache.rb
|
22
|
+
- README.md
|
23
|
+
- LICENSE
|
24
|
+
has_rdoc: true
|
25
|
+
homepage: https://github.com/mscharley/ruby-blockcache
|
26
|
+
licenses: []
|
27
|
+
post_install_message:
|
28
|
+
rdoc_options: []
|
29
|
+
require_paths:
|
30
|
+
- lib
|
31
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
32
|
+
none: false
|
33
|
+
requirements:
|
34
|
+
- - ! '>='
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ! '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
requirements: []
|
44
|
+
rubyforge_project:
|
45
|
+
rubygems_version: 1.6.2
|
46
|
+
signing_key:
|
47
|
+
specification_version: 3
|
48
|
+
summary: Cache implemented in Ruby that knows how to update its own contents
|
49
|
+
test_files: []
|