1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
module Mongo
module ServerSelection
module Read
# Represents a Server Selection specification test.
#
# @since 2.0.0
class Spec
# Mapping of topology description strings to topology type classes.
#
# @since 2.0.0
TOPOLOGY_TYPES = {
'ReplicaSetNoPrimary' => Mongo::Cluster::Topology::ReplicaSet,
'ReplicaSetWithPrimary' => Mongo::Cluster::Topology::ReplicaSet,
'Sharded' => Mongo::Cluster::Topology::Sharded,
'Single' => Mongo::Cluster::Topology::Single,
'Unknown' => Mongo::Cluster::Topology::Unknown
}
# Mapping of read preference modes.
#
# @since 2.0.0
READ_PREFERENCES = {
'Primary' => :primary,
'Secondary' => :secondary,
'PrimaryPreferred' => :primary_preferred,
'SecondaryPreferred' => :secondary_preferred,
'Nearest' => :nearest,
}
# @return [ String ] description The spec description.
#
# @since 2.0.0
attr_reader :description
# @return [ Hash ] read_preference The read preference to be used for selection.
#
# @since 2.0.0
attr_reader :read_preference
# @return [ Integer ] heartbeat_frequency The heartbeat frequency to be set on the client.
#
# @since 2.4.0
attr_reader :heartbeat_frequency
# @return [ Integer ] max_staleness The max_staleness.
#
# @since 2.4.0
attr_reader :max_staleness
# @return [ Array<Hash> ] eligible_servers The eligible servers before the latency
# window is taken into account.
#
# @since 2.0.0
attr_reader :eligible_servers
# @return [ Array<Hash> ] suitable_servers The set of servers matching all server
# selection logic. May be a subset of eligible_servers and/or candidate_servers.
#
# @since 2.0.0
attr_reader :suitable_servers
# @return [ Mongo::Cluster::Topology ] type The topology type.
#
# @since 2.0.0
attr_reader :type
# Instantiate the new spec.
#
# @example Create the spec.
# Spec.new(file)
#
# @param [ String ] file The name of the file.
#
# @since 2.0.0
def initialize(file)
file = File.new(file)
@test = YAML.load(ERB.new(file.read).result)
file.close
@description = "#{@test['topology_description']['type']}: #{File.basename(file)}"
@heartbeat_frequency = @test['heartbeatFrequencyMS'] / 1000 if @test['heartbeatFrequencyMS']
@read_preference = @test['read_preference']
@read_preference['mode'] = READ_PREFERENCES[@read_preference['mode']]
@max_staleness = @read_preference['maxStalenessSeconds']
@candidate_servers = @test['topology_description']['servers']
@suitable_servers = @test['suitable_servers'] || []
@in_latency_window = @test['in_latency_window'] || []
@type = TOPOLOGY_TYPES[@test['topology_description']['type']]
end
# Whether this spec describes a replica set.
#
# @example Determine if the spec describes a replica set.
# spec.replica_set?
#
# @return [true, false] If the spec describes a replica set.
#
# @since 2.0.0
def replica_set?
type == Mongo::Cluster::Topology::ReplicaSet
end
# Does this spec expect a server to be found.
#
# @example Will a server be found with this spec.
# spec.server_available?
#
# @return [true, false] If a server will be found with this spec.
#
# @since 2.0.0
def server_available?
!in_latency_window.empty?
end
# Is the max staleness setting invalid.
#
# @example Will the max staleness setting be valid with other options.
# spec.invalid_max_staleness?
#
# @return [ true, false ] If an error will be raised by the max staleness setting.
#
# @since 2.4.0
def invalid_max_staleness?
@test['error']
end
# The subset of suitable servers that falls within the allowable latency
# window.
# We have to correct for our server selection algorithm that adds the primary
# to the end of the list for SecondaryPreferred read preference mode.
#
# @example Get the list of suitable servers within the latency window.
# spec.in_latency_window
#
# @return [ Array<Hash> ] The servers within the latency window.
#
# @since 2.0.0
def in_latency_window
if read_preference['mode'] == :secondary_preferred && primary
return @in_latency_window.push(primary).uniq
end
@in_latency_window
end
# The servers a topology would return as candidates for selection.
#
# @return [ Array<Hash> ] candidate_servers The candidate servers.
#
# @since 2.0.0
def candidate_servers
@candidate_servers.select { |s| s['type'] != 'Unknown' }
end
private
def primary
@candidate_servers.find { |s| s['type'] == 'RSPrimary' }
end
end
end
end
end
|