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.
Files changed (4) hide show
  1. data/LICENSE +21 -0
  2. data/README.md +44 -0
  3. data/lib/blockcache.rb +120 -0
  4. 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.
@@ -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.
@@ -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: []