cacheAR 0.9.0

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 (3) hide show
  1. data/cacheAR-CHANGES +0 -0
  2. data/lib/cachear.rb +218 -0
  3. metadata +38 -0
File without changes
@@ -0,0 +1,218 @@
1
+ ########################################
2
+ #
3
+ # Author:: Dmitry V. Sabanin <dmitry@sabanin.ru>
4
+ # Copyright:: Copyright (c) 2005 MuraveyLabs, Ltd
5
+ # URL:: http://muravey.net/opensource/
6
+ # Revision:: $Date: 2004/11/17 07:37:13 $ $Revision: 1.7 $
7
+ # License:: MIT
8
+ #
9
+ ########################################
10
+
11
+ require_gem 'ruby-cache'
12
+
13
+ # ActiveRecord::MemoryCache.logger = ActiveRecord::Base.logger
14
+ # ActiveRecord::Base.cacher = ActiveRecord::MemoryCache.instance
15
+ module ActiveRecord::Caching
16
+
17
+ def self.append_features(base)
18
+ super
19
+ base.class_eval do
20
+ cattr_accessor :cacher
21
+ class << self
22
+ alias_method :ar_find_by_sql, :find_by_sql
23
+ alias_method :ar_count_by_sql, :count_by_sql
24
+ undef :find_by_sql, :count_by_sql
25
+
26
+ def find_by_sql(sql)
27
+ cacher.cache_query( self, sanitize_sql(sql) ) do |s|
28
+ ar_find_by_sql(s)
29
+ end
30
+ end
31
+
32
+ def count_by_sql(sql)
33
+ cacher.cache_query( self, sanitize_sql(sql) ) do |s|
34
+ ar_count_by_sql(s)
35
+ end
36
+ end
37
+
38
+ def ===(inst)
39
+ i = 0
40
+ while( (kl = inst.class.ancestors[i]) != Object )
41
+ return true if self.to_s == kl.to_s
42
+ i += 1
43
+ end
44
+ super
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+
53
+ def kind_of?(klass)
54
+ return true if klass === self
55
+ super
56
+ end
57
+
58
+ def is_a?(klass)
59
+ kind_of?(klass)
60
+ end
61
+
62
+ def after_save
63
+ self.class.cacher.expire(self.class)
64
+ end
65
+
66
+ end
67
+
68
+ ActiveRecord::Base.class_eval do
69
+ include ActiveRecord::Caching
70
+ end
71
+
72
+ class ActiveRecord::CacheSQLQuery
73
+
74
+ RE_TABLES = /FROM(.+?)(?:(WHERE)|(LIMIT)|($))/i
75
+
76
+ attr_reader :sql
77
+
78
+ @@queries = Hash.new { |hsh, query| hsh[query] = self.new(query) }
79
+
80
+ def self.create(str)
81
+ @@queries[str]
82
+ end
83
+
84
+ def initialize(str)
85
+ @sql = str.gsub(/[\r\n]/,' ')
86
+ end
87
+
88
+ def tables
89
+ return @tables if @tables
90
+ raw = @sql.scan(RE_TABLES).flatten[0].strip.split(/,/)
91
+ @tables = raw.map do |r|
92
+ r.strip.gsub(/\s+.+$/,'').strip
93
+ end.uniq
94
+ end
95
+
96
+ def to_s
97
+ @sql
98
+ end
99
+
100
+ def to_str
101
+ to_s
102
+ end
103
+
104
+ def inspect
105
+ "<sql: #{to_s.inspect}>"
106
+ end
107
+
108
+ def == (oth)
109
+ @sql == oth.sql
110
+ end
111
+
112
+ def eql?(oth)
113
+ self == oth
114
+ end
115
+
116
+ end
117
+
118
+ class ActiveRecord::CacheInstance
119
+
120
+ def initialize(inst)
121
+ begin
122
+ @inst = inst.dup
123
+ rescue TypeError
124
+ @inst = inst
125
+ end
126
+ @expired = false
127
+ end
128
+
129
+ def instance
130
+ begin
131
+ @inst.dup
132
+ rescue
133
+ @inst
134
+ end
135
+ end
136
+
137
+ def expire!
138
+ @inst = nil
139
+ @expired = true
140
+ end
141
+
142
+ def expired?
143
+ @expired
144
+ end
145
+
146
+ end
147
+
148
+ class ActiveRecord::MemoryCache
149
+
150
+ include Singleton
151
+
152
+ cattr_accessor :max_size
153
+
154
+ # Maximal cache size for one model is 10MB by default
155
+ @@max_size = 10 * 1024 * 1024
156
+
157
+ cattr_accessor :log
158
+ @@log = false
159
+
160
+ cattr_accessor :logger
161
+
162
+ def initialize
163
+ @tables = Hash.new do |hsh, table|
164
+ hsh[table] = Cache.new
165
+ end
166
+ end
167
+
168
+ def cache_query(klass, sql, &blk)
169
+ sql = ActiveRecord::CacheSQLQuery.create(sql)
170
+ tbl = klass.table_name()
171
+ if @tables[tbl].cached?(sql) and !@tables[tbl][sql].expired?
172
+ log_hit(sql)
173
+ inst = @tables[tbl][sql].instance
174
+ inst
175
+ else
176
+ log_miss(sql)
177
+ inst = store_result( sql, blk.call(sql.to_s) ).instance
178
+ inst
179
+ end
180
+ end
181
+
182
+ def expire(klass)
183
+ if(cache = @tables[ klass.table_name() ])
184
+ cache.each do |key, inst|
185
+ inst.expire!
186
+ cache.delete(key)
187
+ end
188
+ end
189
+ end
190
+
191
+ private
192
+
193
+ def store_result(sql, obj)
194
+ inst = ActiveRecord::CacheInstance.new( obj )
195
+ sql.tables.each do |tbl|
196
+ @tables[tbl].store(sql, inst)
197
+ end
198
+ inst
199
+ end
200
+
201
+ def log_hit(sql)
202
+ do_log("Cache hit for tables #{sql.tables.inspect}: #{sql.inspect}")
203
+ end
204
+
205
+ def log_miss(sql)
206
+ do_log("Cache miss for tables #{sql.tables.inspect}: #{sql.inspect}")
207
+ end
208
+
209
+ def log_stats
210
+ size, num, hits, misses = @cache[tbl].statistics
211
+ do_log("Cache stat for #{tbl}: size=#{size}B; num=#{num}; hits=#{hits}; misses=#{misses}")
212
+ end
213
+
214
+ def do_log(str)
215
+ logger.info(str) if log
216
+ end
217
+
218
+ end
metadata ADDED
@@ -0,0 +1,38 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.6
3
+ specification_version: 1
4
+ name: cacheAR
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.9.0
7
+ date: 2005-04-09
8
+ summary: cacheAR is a tiny Ruby on Rails add-on to enable support of caching ActiveRecord lookup results.
9
+ require_paths:
10
+ - lib
11
+ email: dmitry@sabanin.ru
12
+ homepage: http://rubyforge.org/projects/muravey-tools
13
+ rubyforge_project: muravey-tools
14
+ description:
15
+ autorequire: cachear
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ authors:
28
+ - Dmitry V. Sabanin
29
+ files:
30
+ - lib/cachear.rb
31
+ - cacheAR-CHANGES
32
+ test_files: []
33
+ rdoc_options: []
34
+ extra_rdoc_files: []
35
+ executables: []
36
+ extensions: []
37
+ requirements: []
38
+ dependencies: []