-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
API cache extracted from mloughran.com.
Some major limitations right now: * Only the :cache and :timeout options are implemented * There is only one cache store and it's an in memory hash
- Loading branch information
Martyn Loughran
committed
May 29, 2008
0 parents
commit de636b0
Showing
9 changed files
with
167 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pkg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
Copyright (c) 2008 Martyn Loughran | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
"Software"), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
api_cache | ||
========= | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
require 'rubygems' | ||
require 'rake/gempackagetask' | ||
require 'rubygems/specification' | ||
require 'date' | ||
|
||
PLUGIN = "api_cache" | ||
NAME = "api_cache" | ||
GEM_VERSION = "0.0.1" | ||
AUTHOR = "Martyn Loughran" | ||
EMAIL = "me@mloughran.com" | ||
HOMEPAGE = "http://merb-plugins.rubyforge.org/api_cache/" | ||
SUMMARY = "Library to handle caching external API calls" | ||
|
||
spec = Gem::Specification.new do |s| | ||
s.name = NAME | ||
s.version = GEM_VERSION | ||
s.platform = Gem::Platform::RUBY | ||
s.has_rdoc = true | ||
s.extra_rdoc_files = ["README", "LICENSE", 'TODO'] | ||
s.summary = SUMMARY | ||
s.description = s.summary | ||
s.author = AUTHOR | ||
s.email = EMAIL | ||
s.homepage = HOMEPAGE | ||
s.require_path = 'lib' | ||
s.autorequire = PLUGIN | ||
s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,spec}/**/*") | ||
end | ||
|
||
Rake::GemPackageTask.new(spec) do |pkg| | ||
pkg.gem_spec = spec | ||
end | ||
|
||
desc "install the plugin locally" | ||
task :install => [:package] do | ||
sh %{sudo gem install pkg/#{NAME}-#{GEM_VERSION} --no-update-sources} | ||
end | ||
|
||
desc "create a gemspec file" | ||
task :make_spec do | ||
File.open("#{GEM}.gemspec", "w") do |file| | ||
file.puts spec.to_ruby | ||
end | ||
end |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
class APICache | ||
class Error < RuntimeError; end | ||
class Invalid < RuntimeError; end | ||
|
||
class << self | ||
attr_accessor :cache | ||
end | ||
|
||
# Initializes the cache | ||
def self.start | ||
APICache.cache = APICache::MemoryStore.new | ||
end | ||
|
||
# Raises an APICache::Error if it can't get a value. You should rescue this. | ||
# | ||
# Optionally call with a block. The value of the block is then used to | ||
# set the cache rather than calling the url. Use it for example if you need | ||
# to make another type of request, catch custom error codes etc. To signal | ||
# that the call failed just throw :invalid - the value will then not be | ||
# cached and the api will not be called again for options[:timeout] seconds. | ||
# | ||
# For example: | ||
# [Add example here] | ||
def self.get(url, options = {}, &block) | ||
options = { | ||
:cache => 600, # 10 minutes After this time fetch new value | ||
:valid => 86400, # 1 day Expire even if not fetched new data | ||
:period => 60, # 1 minute Don't call API more frequently than this | ||
:timeout => 5 # 5 seconds Timeout to wait for response | ||
}.merge(options) | ||
|
||
if cache.exists?(url) && !cache.expired?(url, options[:cache]) | ||
# Cache is populated and not expired | ||
cache.get(url) | ||
else | ||
# Cache is not populated or is expired | ||
begin | ||
r = Timeout::timeout(options[:timeout]) do | ||
if block_given? | ||
# This should raise APICache::Invalid if it is not correct | ||
yield | ||
else | ||
r = Net::HTTP.get_response(URI.parse(url)).body | ||
# TODO: Check that it's a 200 response | ||
end | ||
end | ||
cache.set(url, r) | ||
rescue Timeout::Error, APICache::Invalid | ||
if cache.exists?(url) | ||
cache.get(url) | ||
else | ||
raise APICache::Error | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
require 'api_cache/memory_store' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
class APICache::MemoryStore | ||
def initialize | ||
puts "Init cache" | ||
@cache = {} | ||
end | ||
|
||
def expired?(name, timeout) | ||
Time.now - created(name) > timeout | ||
end | ||
|
||
def set(name, value) | ||
puts "Setting the cache" | ||
@cache[name] = [Time.now, value] | ||
value | ||
end | ||
|
||
def get(name) | ||
puts "Serving from cache" | ||
@cache[name][1] | ||
end | ||
|
||
def exists?(name) | ||
!@cache[name].nil? | ||
end | ||
|
||
private | ||
|
||
def created(name) | ||
@cache[name][0] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
require File.dirname(__FILE__) + '/spec_helper' | ||
|
||
describe "api_cache" do | ||
it "should do nothing" do | ||
true.should == true | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
$TESTING=true | ||
$:.push File.join(File.dirname(__FILE__), '..', 'lib') |