feedtools-cache-memcached 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt ADDED
File without changes
data/History.txt ADDED
File without changes
data/INSTALL.txt ADDED
@@ -0,0 +1,16 @@
1
+ INSTALLATION for FeedTools::Cache::Memcached
2
+ ==============================
3
+
4
+ Requirements:
5
+ - Ruby version 1.8.x
6
+ - FeedTools version 0.2.2 or later
7
+ - memcache-client version 1.3.0 or later
8
+
9
+ Installation:
10
+ $ ruby setup.rb config
11
+ $ ruby setup.rb setup
12
+ # ruby setup.rb install
13
+
14
+ or
15
+
16
+ # gem install feedtools-cache-memcached
data/Manifest.txt ADDED
@@ -0,0 +1,14 @@
1
+ CHANGELOG.txt
2
+ History.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ INSTALL.txt
7
+ TUTORIAL.txt
8
+ TODO
9
+ lib/feedtools-cache-memcached.rb
10
+ lib/feedtools/cache/memcached.rb
11
+ lib/feedtools/cache/memcached/version.rb
12
+ setup.rb
13
+ test/test_helper.rb
14
+ test/test_feedtools-cache-memcached.rb
data/README.txt ADDED
@@ -0,0 +1,21 @@
1
+ README for FeedTools::Cache::Memcached
2
+ ===================================
3
+
4
+ What is:
5
+ FeedTools::Cache::Memcached provides cache capability with memcached for FeedTools.
6
+
7
+ Requirements:
8
+ - ruby-1.8.x: http://www.ruby-lang.org/
9
+ - FeedTools: http://rubyforge.org/projects/feedtools/
10
+ - 0.2.2 or later
11
+ - memcache-client: http://rubyforge.org/projects/seattlerb/
12
+ - 1.3.0 or later
13
+
14
+ Installation:
15
+ see INSTALL.*
16
+
17
+ Documentations:
18
+ see rdoc
19
+
20
+ License:
21
+ Ruby's
data/Rakefile ADDED
@@ -0,0 +1,82 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'fileutils'
10
+ require 'hoe'
11
+ include FileUtils
12
+ require File.join(File.dirname(__FILE__), 'lib', 'feedtools', 'cache', 'memcached', 'version')
13
+
14
+ AUTHOR = "date"
15
+ EMAIL = "itacchi@gmail.com"
16
+ DESCRIPTION = "memcached cache plugin for FeedTools"
17
+ GEM_NAME = "feedtools-cache-memcached"
18
+ RUBYFORGE_PROJECT = "feedtools-cache"
19
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
20
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
21
+
22
+ NAME = "FeedTools::Cache::Memcached"
23
+ REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
24
+ VERS = ENV['VERSION'] || (FeedTools::Cache::Memcached::VERSION::STRING + (REV ? ".#{REV}" : ""))
25
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
26
+ RDOC_OPTS = ['--quiet', '--title', "FeedTools::Cache::Memcached documentation",
27
+ "--opname", "index.html",
28
+ "--line-numbers",
29
+ "--main", "README",
30
+ "--inline-source"]
31
+
32
+ class Hoe
33
+ def extra_deps
34
+ @extra_deps.reject { |x| Array(x).first == 'hoe' }
35
+ end
36
+ end
37
+
38
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
39
+ p.author = AUTHOR
40
+ p.description = DESCRIPTION
41
+ p.email = EMAIL
42
+ p.summary = DESCRIPTION
43
+ p.url = HOMEPATH
44
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
45
+ p.test_globs = ["test/**/*_test.rb"]
46
+ p.clean_globs = CLEAN
47
+
48
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
49
+ p.extra_deps = [ ['memcache-client', '>= 1.3.0'] ]
50
+ end
51
+
52
+ desc 'Generate website files'
53
+ task :website_generate do
54
+ Dir['website/**/*.txt'].each do |txt|
55
+ sh %{ ruby scripts/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} } end
56
+ end
57
+
58
+ desc 'Upload website files to rubyforge'
59
+ task :website_upload do
60
+ config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
61
+ host = "#{config["username"]}@rubyforge.org"
62
+ remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/"
63
+ local_dir = 'website'
64
+ sh %{rsync -av #{local_dir}/ #{host}:#{remote_dir}}
65
+ end
66
+
67
+ desc 'Generate and upload website files'
68
+ task :website => [:website_generate, :website_upload]
69
+
70
+ desc 'Release the website and new gem version'
71
+ task :deploy => [:check_version, :website, :release]
72
+
73
+ task :check_version do
74
+ unless ENV['VERSION']
75
+ puts 'Must pass a VERSION=x.y.z release version'
76
+ exit
77
+ end
78
+ unless ENV['VERSION'] == VERS
79
+ puts "Please update your version.rb to match the release version, currently #{VERS}"
80
+ exit
81
+ end
82
+ end
data/TODO ADDED
File without changes
data/TUTORIAL.txt ADDED
@@ -0,0 +1,31 @@
1
+ TUTORIAL for FeedTools::Cache::Memcached
2
+ ==============================
3
+
4
+ 1. install ruby
5
+ At first, you install Ruby the Object-Oriented Scripting Language.
6
+ Go http://www.ruby-lang.org/en/.
7
+
8
+ 2. install feedtools
9
+ Just type `gem install feedtools'.
10
+
11
+ 3. install FeedTools::Cache::Memcached
12
+ See INSTALL.txt
13
+
14
+ 4. write code
15
+ require 'feedtools'
16
+ require 'feedtools-cache-memcached'
17
+ # or if you manually installed , require 'feedtools/cache/memcached'
18
+
19
+ # set cache configration
20
+ FeedTools.configurations[:feed_cache] = FeedTools::Cache::Memcached
21
+
22
+ # set memcached configration
23
+ FeedTools::Cache::Memcached.configration = ['localhost:11211']
24
+
25
+ # fetch from the web
26
+ feed = FeedTools::Feed.open('http://dontstopmusic.no-ip.org/diary/index.rdf')
27
+ p feed.live? #=> true
28
+
29
+ # use the cache
30
+ feed = FeedTools::Feed.open('http://dontstopmusic.no-ip.org/diary/index.rdf')
31
+ p feed.live? #=> false
@@ -0,0 +1 @@
1
+ Dir[File.join(File.dirname(__FILE__), 'feedtools/**/*.rb')].sort.each { |lib| require lib }
@@ -0,0 +1,287 @@
1
+ require 'digest/sha1'
2
+ begin
3
+ require 'rubygems'
4
+ rescue LoadError
5
+ end
6
+ require 'memcache'
7
+
8
+ module FeedTools
9
+ module Cache #:nodoc:
10
+ class Memcached
11
+ end
12
+ end
13
+ end
14
+
15
+ class FeedTools::Cache::Memcached
16
+ class NullLogger #:nodoc:
17
+ def method_missing(message, *args)
18
+ end
19
+ end
20
+ end
21
+
22
+
23
+ # Caching plugin for FeedTools. Cache feched feed into memcached.
24
+ #
25
+ # === usage
26
+ # Simple to use, you require the library and a set configuration.
27
+ # require 'feedtools-cache-memcached'
28
+ # or manually installed
29
+ # require 'feedtools/cache/memcached'
30
+ #
31
+ # FeedTools.configurations[:feed_cache] = FeedTools::Cache::Memcached
32
+ #
33
+ # === configuration
34
+ # You can configurate memcached servers to use.
35
+ # 1. FeedTools::Cache::Memcached.configuration
36
+ # 2. default: localhost:11211 and { :namespace => nil, :readonly => false, :multithread => false, }
37
+ class FeedTools::Cache::Memcached
38
+ # Required by FeedTools.
39
+ ATTRIBUTES = %w(
40
+ id href title link
41
+ feed_data feed_data_type
42
+ http_headers last_retrieved
43
+ )
44
+
45
+ # default configuration from memcache-client
46
+ @@configuration = ['localhost:11211', { :namespace => nil, :readonly => false, :multithread => false, }]
47
+ @@logger = NullLogger.new
48
+
49
+ # Required by FeedTools.
50
+ # Find a cached feed by its key.
51
+ # === Parameters
52
+ # [id] <code>String</code>: primary key.
53
+ #
54
+ # === Returns
55
+ # [cached feed] <code>FeedTools::Cache::YAML</code>: cached feed. If not found, returns <code>nil</code>.
56
+ def self.find_by_id(id)
57
+ create_from_memcached(key_by_id(id))
58
+ end
59
+
60
+ # Required by FeedTools.
61
+ # Find a cached feed by its url.
62
+ # === Parameters
63
+ # [url] <code>String</code>: feed url.
64
+ #
65
+ # === Returns
66
+ # [cached feed] <code>FeedTools::Cache::YAML</code>: cached feed. If not found, returns <code>nil</code>.
67
+ def self.find_by_href(url)
68
+ create_from_memcached(key_by_url(url))
69
+ end
70
+
71
+ # Required by FeedTools.
72
+ # TODO: implement this.
73
+ def self.initialize_cache
74
+ # nothing
75
+ end
76
+
77
+ # Required by FeedTools.
78
+ # Return whether this connects memcached or not.
79
+ #
80
+ # === Returns
81
+ # [boolean] <code>true/false</code>: If memcached is avaliable, returns true. If it is not so, returns false.
82
+ #
83
+ def self.connected?
84
+ @@memcached.active?
85
+ end
86
+
87
+ # Required by FeedTools.
88
+ # TODO: implement this.
89
+ #
90
+ # === Returns
91
+ # Currently always true.
92
+ def self.set_up_correctly?
93
+ true
94
+ end
95
+
96
+ # Get memcached configuration
97
+ #
98
+ # === Returns
99
+ # [configuration] <code>Array</code> : configured memcached settings.
100
+ def self.configuration
101
+ @@configuration
102
+ end
103
+
104
+ # Set memcached configuration
105
+ #
106
+ # === Parameters
107
+ # [configuration] <code>String</code> : set memcached configuration and reset the current connections.
108
+ def self.configuration=(configuration)
109
+ @@configuration = configuration
110
+ @@memcached.reset
111
+ end
112
+
113
+ # Debug logger.
114
+ #
115
+ # === Returns
116
+ # [path] <code>String</code> : logger instance. Default is NullLogger (nothing to do).
117
+ def self.logger
118
+ @@logger
119
+ end
120
+
121
+ # Set logger object if use need. Logger output messages when log level is DEBUG.
122
+ #
123
+ # === Parameters
124
+ # [logger] <code>logger</code> : set logger.
125
+ def self.logger=(logger)
126
+ @@logger = logger
127
+ end
128
+
129
+ # Create a FeedTools::Cache::Memcached instance object.
130
+ #
131
+ # === Returns
132
+ # [cached feed] <code>FeedTools::Cache::Memcached</code> : cached feed.
133
+ # Create a FeedTools::Cache::Memcached instance object.
134
+ #
135
+ # === Returns
136
+ # [cached feed] <code>FeedTools::Cache::Memcached </code> : cached feed.
137
+ def initialize
138
+ @data = {}
139
+ @new_record = true
140
+ @@memcached ||= MemCache.new(*@@configuration)
141
+ end
142
+
143
+ # Required by FeedTools.
144
+ #
145
+ # Returns whether it is a new object.
146
+ #
147
+ # === Returns
148
+ # [boolean] <code>true/false</code> : returns <code>true</code> if the instance has not been saved yet. Returns false if the instance loaded from cache.
149
+ def new_record?
150
+ @new_record
151
+ end
152
+
153
+ # Required by FeedTools.
154
+ #
155
+ # Primary key.
156
+ #
157
+ # === Returns
158
+ # [id] <code>String</code> : primary key.
159
+ def id
160
+ @data['id']
161
+ end
162
+
163
+ # Required by FeedTools.
164
+ #
165
+ # Set primary key.
166
+ #
167
+ # === Parameters
168
+ # [id] <code>String</code> : primary key.
169
+ def id=(id)
170
+ @data['id'] = id
171
+ end
172
+
173
+ # Required by FeedTools.
174
+ #
175
+ # Save new or update instance.
176
+ def save
177
+ unless id
178
+ save_new_cache
179
+ else
180
+ update_cache
181
+ end
182
+ end
183
+
184
+ # Load data from memcached.
185
+ #
186
+ # === Parameters
187
+ # [key] <code>String</code> : cache key.
188
+ def load_cache(key)
189
+ begin
190
+ @data = @@memcached.get(key) || {}
191
+ @new_record = false
192
+ debug "load cache: #{key}"
193
+ self
194
+ rescue
195
+ nil
196
+ end
197
+ end
198
+
199
+ def method_missing(message, *args) #:nodoc:
200
+ begin
201
+ if matched = /^(.*)=$/.match(message.to_s)
202
+ set_attribute(matched[1], args.first)
203
+ else
204
+ get_attribute(message.to_s)
205
+ end
206
+ rescue NameError
207
+ raise NoMethodError, "undefined method `#{message}' for #{self.to_s}"
208
+ end
209
+ end
210
+
211
+ private
212
+ def self.create_from_memcached(key)
213
+ self.new.load_cache(key)
214
+ end
215
+
216
+ def self.key_by_id(id)
217
+ @@memcached[id]
218
+ end
219
+
220
+ def self.key_by_url(url)
221
+ normalize_url(url)
222
+ end
223
+
224
+ def self.normalize_url(url)
225
+ uri = URI.parse(url).normalize
226
+ url = uri.host
227
+ url += ":#{uri.port}" unless uri.port == 80
228
+ url += uri.request_uri
229
+ end
230
+
231
+ def key_by_id
232
+ self.class.key_by_id(id)
233
+ end
234
+
235
+ def key_by_url
236
+ self.class.key_by_url(href)
237
+ end
238
+
239
+ def save_new_cache
240
+ debug "save new cache: #{href}"
241
+ self.id = generate_id
242
+ write_cache(key_by_url)
243
+ associate_url_and_id(key_by_url, @data['id'])
244
+ end
245
+
246
+ def update_cache
247
+ debug "update cache: #{href}"
248
+ write_cache(key_by_url)
249
+ end
250
+
251
+ def write_cache(key)
252
+ debug "\twrite cache: #{key}"
253
+ @@memcached[key] = @data
254
+ end
255
+
256
+ def associate_url_and_id(url, id)
257
+ @@memcached[id] = url
258
+ end
259
+
260
+ def generate_id
261
+ Digest::SHA1.hexdigest('%0x' % object_id + Time.now.to_i.to_s)
262
+ end
263
+
264
+ def get_attribute(attribute)
265
+ if ATTRIBUTES.include?(attribute)
266
+ @data[attribute]
267
+ else
268
+ raise NameError
269
+ end
270
+ end
271
+
272
+ def set_attribute(attribute, value)
273
+ if ATTRIBUTES.include?(attribute)
274
+ @data[attribute] = value
275
+ else
276
+ raise NameError
277
+ end
278
+ end
279
+
280
+ def debug(message)
281
+ message = "[#{self.class}] #{message}"
282
+ @@logger.debug message
283
+ if $DEBUG
284
+ STDERR.puts message
285
+ end
286
+ end
287
+ end