RUBY-284 document :read API

This commit is contained in:
Kyle Banker 2011-09-06 14:58:03 -04:00
parent 5d83ab2460
commit 50c38c6c6b
8 changed files with 78 additions and 39 deletions

View File

@ -34,6 +34,11 @@ module Mongo
# for insert, update, and remove method called on this Collection instance. If no
# value is provided, the default value set on this instance's DB will be used. This
# default can be overridden for any invocation of insert, update, or remove.
# @option options [:primary, :secondary] :read The default read preference for queries
# initiates from this connection object. If +:secondary+ is chosen, reads will be sent
# to one of the closest available secondary nodes. If a secondary node cannot be located, the
# read will be sent to the primary. If this option is left unspecified, the value of the read
# preference for this collection's associated Mongo::DB object will be used.
#
# @raise [InvalidNSName]
# if collection name is empty, contains '$', or starts or ends with '.'
@ -84,8 +89,12 @@ module Mongo
@cache = Hash.new(0)
unless pk_factory
@safe = opts.fetch(:safe, @db.safe)
@read = opts.fetch(:read, @db.read_preference)
@read_preference = @read.is_a?(Hash) ? @read.dup : @read
if value = opts[:read]
Mongo::Support.validate_read_preference(value)
else
value = @db.read_preference
end
@read_preference = value.is_a?(Hash) ? value.dup : value
end
@pk_factory = pk_factory || opts[:pk] || BSON::ObjectId
@hint = nil
@ -157,6 +166,11 @@ module Mongo
# you can cut down on network traffic and decoding time. If using a Hash, keys should be field
# names and values should be either 1 or 0, depending on whether you want to include or exclude
# the given field.
# @option opts [:primary, :secondary] :read The default read preference for queries
# initiates from this connection object. If +:secondary+ is chosen, reads will be sent
# to one of the closest available secondary nodes. If a secondary node cannot be located, the
# read will be sent to the primary. If this option is left unspecified, the value of the read
# preference for this Collection object will be used.
# @option opts [Integer] :skip number of documents to skip from the beginning of the result set
# @option opts [Integer] :limit maximum number of documents to return
# @option opts [Array] :sort an array of [key, direction] pairs to sort by. Direction should

View File

@ -685,6 +685,7 @@ module Mongo
@connect_timeout = opts[:connect_timeout] || nil
# Mutex for synchronizing pool access
# TODO: remove this.
@connection_mutex = Mutex.new
# Global safe option. This is false by default.

View File

@ -70,8 +70,12 @@ module Mongo
@query_run = false
@transformer = opts[:transformer]
read = opts[:read] || collection.read_preference
@read_preference = read.is_a?(Hash) ? read.dup : read
if value = opts[:read]
Mongo::Support.validate_read_preference(value)
else
value = collection.read_preference
end
@read_preference = value.is_a?(Hash) ? value.dup : value
batch_size(opts[:batch_size] || 0)
@full_collection_name = "#{@collection.db.name}.#{@collection.name}"

View File

@ -82,8 +82,12 @@ module Mongo
@strict = opts[:strict]
@pk_factory = opts[:pk]
@safe = opts.fetch(:safe, @connection.safe)
read = opts.fetch(:read, @connection.read_preference)
@read_preference = read.is_a?(Hash) ? read.dup : read
if value = opts[:read]
Mongo::Support.validate_read_preference(value)
else
value = @connection.read_preference
end
@read_preference = value.is_a?(Hash) ? value.dup : value
@cache_time = opts[:cache_time] || 300 #5 minutes.
end

View File

@ -41,8 +41,10 @@ module Mongo
# propogated to DB objects instantiated off of this Connection. This
# default can be overridden upon instantiation of any DB by explicity setting a :safe value
# on initialization.
# @option options [Boolean] :read_secondary(false) If true, a random secondary node will be chosen,
# and all reads will be directed to that node.
# @option options [:primary, :secondary] :read (:primary) The default read preference for Mongo::DB
# objects created from this connection object. If +:secondary+ is chosen, reads will be sent
# to one of the closest available secondary nodes. If a secondary node cannot be located, the
# read will be sent to the primary.
# @option options [Logger, #debug] :logger (nil) Logger instance to receive driver operation log.
# @option options [Integer] :pool_size (1) The maximum number of socket connections allowed per
# connection pool. Note: this setting is relevant only for multi-threaded applications.
@ -125,6 +127,7 @@ module Mongo
@read = :secondary
else
@read = opts.fetch(:read, :primary)
Mongo::Support.validate_read_preference(@read)
end
@connected = false

View File

@ -44,7 +44,6 @@ module Mongo
Digest::MD5.hexdigest("#{username}:mongo:#{plaintext}")
end
def validate_db_name(db_name)
unless [String, Symbol].include?(db_name.class)
raise TypeError, "db_name must be a string or symbol"
@ -59,6 +58,15 @@ module Mongo
db_name
end
def validate_read_preference(value)
if [:primary, :secondary, nil].include?(value)
return true
else
raise MongoArgumentError, "#{value} is not a valid read preference. " +
"Please specify either :primary or :secondary."
end
end
def format_order_clause(order)
case order
when String, Symbol then string_as_sort_parameters(order)

View File

@ -1,41 +1,43 @@
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
require './test/replica_sets/rs_test_helper'
# TODO: enable this once we enable reads from tags.
class ReadPreferenceTest < Test::Unit::TestCase
include Mongo
def setup
@conn = ReplSetConnection.new([RS.host, RS.ports[0], RS.host, RS.ports[1]], :read => :secondary, :pool_size => 50)
@db = @conn.db(MONGO_TEST_DB)
@db.drop_collection("test-sets")
end
#def setup
# @conn = ReplSetConnection.new([RS.host, RS.ports[0], RS.host, RS.ports[1]], :read => :secondary, :pool_size => 50)
# @db = @conn.db(MONGO_TEST_DB)
# @db.drop_collection("test-sets")
#end
def test_query_tagged
col = @db['mongo-test']
# TODO: enable this once we enable reads from tags.
# def test_query_tagged
# col = @db['mongo-test']
col.insert({:a => 1}, :safe => {:w => 3})
col.find_one({}, :read => {:db => "main"})
col.find_one({}, :read => {:dc => "ny"})
col.find_one({}, :read => {:dc => "sf"})
# col.insert({:a => 1}, :safe => {:w => 3})
# col.find_one({}, :read => {:db => "main"})
# col.find_one({}, :read => {:dc => "ny"})
# col.find_one({}, :read => {:dc => "sf"})
assert_raise Mongo::NodeWithTagsNotFound do
col.find_one({}, :read => {:foo => "bar"})
end
# assert_raise Mongo::NodeWithTagsNotFound do
# col.find_one({}, :read => {:foo => "bar"})
# end
threads = []
100.times do
threads << Thread.new do
col.find_one({}, :read => {:dc => "sf"})
end
end
# threads = []
# 100.times do
# threads << Thread.new do
# col.find_one({}, :read => {:dc => "sf"})
# end
# end
threads.each {|t| t.join }
# threads.each {|t| t.join }
col.remove
end
# col.remove
# end
def teardown
RS.restart_killed_nodes
end
#def teardown
# RS.restart_killed_nodes
#end
end

View File

@ -87,11 +87,14 @@ class ReadTest < Test::Unit::TestCase
end
should "allow override alternate value on query" do
@con.expects(:receive_message).with do |o, m, l, s, c, r|
tags = {:dc => "ny"}
end.returns([[], 0, 0])
# TODO: enable this test once we enable reading from tags.
# @con.expects(:receive_message).with do |o, m, l, s, c, r|
# tags = {:dc => "ny"}
# end.returns([[], 0, 0])
@col.find_one({:a => 1}, :read => {:dc => "ny"})
assert_raise MongoArgumentError do
@col.find_one({:a => 1}, :read => {:dc => "ny"})
end
end
end
end