@@ -33,29 +33,56 @@ def self.validate(value)
3333 end
3434 end
3535
36- def select_pool ( mode , tags , latency )
37- return primary_pool if @client . mongos?
36+ def read_preference
37+ {
38+ :mode => @read ,
39+ :tags => @tag_sets ,
40+ :latency => @acceptable_latency
41+ }
42+ end
43+
44+ def read_pool ( read_preference_override = { } )
45+ return primary_pool if mongos?
46+
47+ read_pref = read_preference . merge read_preference_override
48+
49+ if pinned_pool && pinned_pool [ :read_preference ] == read_pref
50+ pool = pinned_pool [ :pool ]
51+ else
52+ unpin_pool
53+ pool = select_pool ( read_pref )
54+ end
55+
56+ unless pool
57+ raise ConnectionFailure , "No replica set member available for query " +
58+ "with read preference matching mode #{ read_pref [ :mode ] } and tags " +
59+ "matching #{ read_pref [ :tags ] } ."
60+ end
61+
62+ pool
63+ end
3864
39- if mode == :primary && !tags . empty?
65+ def select_pool ( read_pref )
66+ if read_pref [ :mode ] == :primary && !read_pref [ :tags ] . empty?
4067 raise MongoArgumentError , "Read preference :primary cannot be combined with tags"
4168 end
4269
43- case mode
70+ case read_pref [ : mode]
4471 when :primary
4572 primary_pool
4673 when :primary_preferred
47- primary_pool || select_secondary_pool ( secondary_pools , tags , latency )
74+ primary_pool || select_secondary_pool ( secondary_pools , read_pref )
4875 when :secondary
49- select_secondary_pool ( secondary_pools , tags , latency )
76+ select_secondary_pool ( secondary_pools , read_pref )
5077 when :secondary_preferred
51- select_secondary_pool ( secondary_pools , tags , latency ) || primary_pool
78+ select_secondary_pool ( secondary_pools , read_pref ) || primary_pool
5279 when :nearest
53- select_secondary_pool ( pools , tags , latency )
80+ select_secondary_pool ( pools , read_pref )
5481 end
5582 end
5683
57- def select_secondary_pool ( candidates , tag_sets , latency )
58- tag_sets = [ tag_sets ] unless tag_sets . is_a? ( Array )
84+ def select_secondary_pool ( candidates , read_pref )
85+ tag_sets = read_pref [ :tags ]
5986
6087 if !tag_sets . empty?
6188 matches = [ ]
@@ -70,10 +97,11 @@ def select_secondary_pool(candidates, tag_sets, latency)
7097 matches = candidates
7198 end
7299
73- matches . empty? ? nil : select_near_pool ( matches , latency )
100+ matches . empty? ? nil : select_near_pool ( matches , read_pref )
74101 end
75102
76- def select_near_pool ( candidates , latency )
103+ def select_near_pool ( candidates , read_pref )
104+ latency = read_pref [ :latency ]
77105 nearest_pool = candidates . min_by { |candidate | candidate . ping_time }
78106 near_pools = candidates . select do |candidate |
79107 ( candidate . ping_time - nearest_pool . ping_time ) <= latency
0 commit comments