Browse files

High availibitiy support if using a replica set connection

Ex: Rack::GridFS::Endpoint.new :db =>
ReplSetConnection.new(['localhost', 30000], ['localhost', 30001]).
db('gridfs')
  • Loading branch information...
1 parent 4da2992 commit 83a13a9949c6ec4806ce444a67810e8e12363bb5 @bmarini bmarini committed with ches Feb 7, 2011
Showing with 85 additions and 36 deletions.
  1. +18 −8 lib/rack/gridfs/endpoint/base.rb
  2. +26 −0 test/caching_test.rb
  3. +36 −0 test/exceptions_test.rb
  4. +5 −28 test/gridfs_test.rb
View
26 lib/rack/gridfs/endpoint/base.rb
@@ -2,10 +2,12 @@ module Rack
class GridFS
class Endpoint
module Base
+ attr_reader :db
def initialize(options = {})
@options = default_options.merge(options)
+ @db = @options[:db]
@lookup = @options[:lookup]
@mapper = @options[:mapper]
end
@@ -24,22 +26,30 @@ def key_for_path(path)
@mapper.respond_to?(:call) ? @mapper.call(path) : path
end
- def db
- @options[:db]
- end
-
protected
def default_options
{ :lookup => :id }
end
def with_rescues
- yield
- rescue Mongo::GridError, BSON::InvalidObjectId => e
+ rescue_connection_failure { yield }
+ rescue Mongo::GridFileNotFound, BSON::InvalidObjectId => e
[ 404, {'Content-Type' => 'text/plain'}, ["File not found. #{e}"] ]
- rescue Mongo::GridFileNotFound
- [ 404, {'Content-Type' => 'text/plain'}, ['File not found.'] ]
+ rescue Mongo::GridError => e
+ [ 500, {'Content-Type' => 'text/plain'}, ["An error occured. #{e}"] ]
+ end
+
+ def rescue_connection_failure(max_retries=60)
+ retries = 0
+ begin
+ yield
+ rescue Mongo::ConnectionFailure => e
+ retries += 1
+ raise e if retries > max_retries
+ sleep(0.5)
+ retry
+ end
end
def response_for(file, request)
View
26 test/caching_test.rb
@@ -22,5 +22,31 @@ def app
get "/gridfs/#{@text_file.filename}"
assert_cache_control "max-age=1800, public"
end
+
+ should "work for small images" do
+ image_id = load_artifact('3wolfmoon.jpg', 'image/jpeg')
+ gridfile = Mongo::Grid.new(db).get(image_id)
+ get "/gridfs/3wolfmoon.jpg"
+ assert last_response.ok?
+ assert_equal 'image/jpeg', last_response.content_type
+ assert_equal gridfile.upload_date.httpdate, last_response.headers["Last-Modified"]
+ assert_equal gridfile.files_id.to_s, last_response.headers["Etag"]
+ end
+
+ should "return 304 when Etag matches" do
+ image_id = load_artifact('3wolfmoon.jpg', 'image/jpeg')
+ gridfile = Mongo::Grid.new(db).get(image_id)
+ get "/gridfs/3wolfmoon.jpg", nil, {'HTTP_IF_NONE_MATCH' => gridfile.files_id.to_s}
+ assert_equal 304, last_response.status
+ end
+
+ should "return 304 when Last-Modified matches" do
+ image_id = load_artifact('3wolfmoon.jpg', 'image/jpeg')
+ gridfile = Mongo::Grid.new(db).get(image_id)
+ get "/gridfs/3wolfmoon.jpg", nil, {'HTTP_IF_MODIFIED_SINCE' => gridfile.upload_date.httpdate}
+ assert_equal 304, last_response.status
+ assert_equal gridfile.files_id.to_s, last_response.headers['Etag']
+ end
+
end
end
View
36 test/exceptions_test.rb
@@ -0,0 +1,36 @@
+require 'test_helper'
+
+class ExceptionsTest < Test::Unit::TestCase
+ include Rack::Test::Methods
+ include Rack::GridFS::Test::Methods
+
+ context "Rack::GridFS Exceptions" do
+ setup do
+ def app
+ setup_app(:lookup => :path)
+ end
+
+ @text_file = load_artifact('test.txt', nil)
+ @html_file = load_artifact('test.html', nil)
+ end
+
+ teardown do
+ db.collection('fs.files').remove
+ end
+
+ should "return a 500 if an error occurs" do
+ Rack::GridFS::Endpoint.any_instance.stubs(:find_file).raises(Mongo::GridError)
+
+ get "/gridfs/anything"
+ assert_equal 500, last_response.status
+ end
+
+ should "retry on connection failure" do
+ gridfile = Mongo::GridFileSystem.new(db).open("test.txt", "r")
+ Rack::GridFS::Endpoint.any_instance.stubs(:find_file).raises(Mongo::ConnectionFailure).then.returns(gridfile)
+
+ get "/gridfs/test.txt"
+ assert last_response.ok?
+ end
+ end
+end
View
33 test/gridfs_test.rb
@@ -30,6 +30,7 @@ def app; setup_app end
context "for lookup by ObjectId" do
setup do
+ def app; setup_app(:lookup => :id) end
@text_id = load_artifact('test.txt', 'text/plain')
@html_id = load_artifact('test.html', 'text/html')
end
@@ -39,22 +40,22 @@ def app; setup_app end
end
should "return TXT files stored in GridFS" do
- get "/gridfs/test.txt"
+ get "/gridfs/#{@text_id}"
assert_equal "Lorem ipsum dolor sit amet.", last_response.body
end
should "return the proper content type for TXT files" do
- get "/gridfs/test.txt"
+ get "/gridfs/#{@text_id}"
assert_equal 'text/plain', last_response.content_type
end
should "return HTML files stored in GridFS" do
- get "/gridfs/test.html"
+ get "/gridfs/#{@html_id}"
assert_match /html.*?body.*Test/m, last_response.body
end
should "return the proper content type for HTML files" do
- get "/gridfs/test.html"
+ get "/gridfs/#{@html_id}"
assert_equal 'text/html', last_response.content_type
end
@@ -63,30 +64,6 @@ def app; setup_app end
assert last_response.not_found?
end
- should "work for small images" do
- image_id = load_artifact('3wolfmoon.jpg', 'image/jpeg')
- gridfile = Mongo::Grid.new(db).get(image_id)
- get "/gridfs/3wolfmoon.jpg"
- assert last_response.ok?
- assert_equal 'image/jpeg', last_response.content_type
- assert_equal gridfile.upload_date.httpdate, last_response.headers["Last-Modified"]
- assert_equal gridfile.files_id.to_s, last_response.headers["Etag"]
- end
-
- should "return 304 when Etag matches" do
- image_id = load_artifact('3wolfmoon.jpg', 'image/jpeg')
- gridfile = Mongo::Grid.new(db).get(image_id)
- get "/gridfs/3wolfmoon.jpg", nil, {'HTTP_IF_NONE_MATCH' => gridfile.files_id.to_s}
- assert_equal 304, last_response.status
- end
-
- should "return 304 when Last-Modified matches" do
- image_id = load_artifact('3wolfmoon.jpg', 'image/jpeg')
- gridfile = Mongo::Grid.new(db).get(image_id)
- get "/gridfs/3wolfmoon.jpg", nil, {'HTTP_IF_MODIFIED_SINCE' => gridfile.upload_date.httpdate}
- assert_equal 304, last_response.status
- assert_equal gridfile.files_id.to_s, last_response.headers['Etag']
- end
end
context "for lookup by filename" do

0 comments on commit 83a13a9

Please sign in to comment.