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 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
|
# Copyright (C) 2014-2017 MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'mongo/server/connectable'
require 'mongo/server/connection'
require 'mongo/server/connection_pool'
require 'mongo/server/context'
require 'mongo/server/description'
require 'mongo/server/monitor'
module Mongo
# Represents a single server on the server side that can be standalone, part of
# a replica set, or a mongos.
#
# @since 2.0.0
class Server
extend Forwardable
include Monitoring::Publishable
# @return [ String ] The configured address for the server.
attr_reader :address
# @return [ Cluster ] cluster The server cluster.
attr_reader :cluster
# @return [ Monitor ] monitor The server monitor.
attr_reader :monitor
# @return [ Hash ] The options hash.
attr_reader :options
# @return [ Monitoring ] monitoring The monitoring.
attr_reader :monitoring
# The default time in seconds to timeout a connection attempt.
#
# @since 2.4.3
CONNECT_TIMEOUT = 10.freeze
# Get the description from the monitor and scan on monitor.
def_delegators :monitor, :description, :scan!, :heartbeat_frequency, :last_scan, :compressor
alias :heartbeat_frequency_seconds :heartbeat_frequency
# Delegate convenience methods to the monitor description.
def_delegators :description,
:arbiter?,
:features,
:ghost?,
:max_wire_version,
:max_write_batch_size,
:max_bson_object_size,
:max_message_size,
:tags,
:average_round_trip_time,
:mongos?,
:other?,
:primary?,
:replica_set_name,
:secondary?,
:standalone?,
:unknown?,
:unknown!,
:last_write_date,
:logical_session_timeout
# Get the app metadata from the cluster.
def_delegators :cluster,
:app_metadata,
:cluster_time,
:update_cluster_time
def_delegators :features,
:check_driver_support!
# Is this server equal to another?
#
# @example Is the server equal to the other?
# server == other
#
# @param [ Object ] other The object to compare to.
#
# @return [ true, false ] If the servers are equal.
#
# @since 2.0.0
def ==(other)
return false unless other.is_a?(Server)
address == other.address
end
# Get a new context for this server in which to send messages.
#
# @example Get the server context.
# server.context
#
# @return [ Mongo::Server::Context ] context The server context.
#
# @since 2.0.0
#
# @deprecated Will be removed in version 3.0
def context
Context.new(self)
end
# Determine if a connection to the server is able to be established and
# messages can be sent to it.
#
# @example Is the server connectable?
# server.connectable?
#
# @return [ true, false ] If the server is connectable.
#
# @since 2.1.0
def connectable?
with_connection do |connection|
connection.connectable?
end
end
# Disconnect the server from the connection.
#
# @example Disconnect the server.
# server.disconnect!
#
# @return [ true ] Always tru with no exception.
#
# @since 2.0.0
def disconnect!
pool.disconnect!
monitor.stop! and true
end
# When the server is flagged for garbage collection, stop the monitor
# thread.
#
# @example Finalize the object.
# Server.finalize(monitor)
#
# @param [ Server::Monitor ] monitor The server monitor.
#
# @since 2.2.0
def self.finalize(monitor)
proc { monitor.stop! }
end
# Instantiate a new server object. Will start the background refresh and
# subscribe to the appropriate events.
#
# @api private
#
# @example Initialize the server.
# Mongo::Server.new('127.0.0.1:27017', cluster, monitoring, listeners)
#
# @note Server must never be directly instantiated outside of a Cluster.
#
# @param [ Address ] address The host:port address to connect to.
# @param [ Cluster ] cluster The cluster the server belongs to.
# @param [ Monitoring ] monitoring The monitoring.
# @param [ Event::Listeners ] event_listeners The event listeners.
# @param [ Hash ] options The server options.
#
# @since 2.0.0
def initialize(address, cluster, monitoring, event_listeners, options = {})
@address = address
@cluster = cluster
@monitoring = monitoring
@options = options.freeze
publish_sdam_event(
Monitoring::SERVER_OPENING,
Monitoring::Event::ServerOpening.new(address, cluster.topology)
)
@monitor = Monitor.new(address, event_listeners, options.merge(app_metadata: cluster.app_metadata))
monitor.scan!
monitor.run!
ObjectSpace.define_finalizer(self, self.class.finalize(monitor))
end
# Get a pretty printed server inspection.
#
# @example Get the server inspection.
# server.inspect
#
# @return [ String ] The nice inspection string.
#
# @since 2.0.0
def inspect
"#<Mongo::Server:0x#{object_id} address=#{address.host}:#{address.port}>"
end
# Get the connection pool for this server.
#
# @example Get the connection pool for the server.
# server.pool
#
# @return [ Mongo::Pool ] The connection pool.
#
# @since 2.0.0
def pool
@pool ||= cluster.pool(self)
end
# Determine if the provided tags are a subset of the server's tags.
#
# @example Are the provided tags a subset of the server's tags.
# server.matches_tag_set?({ 'rack' => 'a', 'dc' => 'nyc' })
#
# @param [ Hash ] tag_set The tag set to compare to the server's tags.
#
# @return [ true, false ] If the provided tags are a subset of the server's tags.
#
# @since 2.0.0
def matches_tag_set?(tag_set)
tag_set.keys.all? do |k|
tags[k] && tags[k] == tag_set[k]
end
end
# Restart the server monitor.
#
# @example Restart the server monitor.
# server.reconnect!
#
# @return [ true ] Always true.
#
# @since 2.1.0
def reconnect!
monitor.restart! and true
end
# Execute a block of code with a connection, that is checked out of the
# server's pool and then checked back in.
#
# @example Send a message with the connection.
# server.with_connection do |connection|
# connection.dispatch([ command ])
# end
#
# @return [ Object ] The result of the block execution.
#
# @since 2.3.0
def with_connection(&block)
pool.with_connection(&block)
end
# Handle authentication failure.
#
# @example Handle possible authentication failure.
# server.handle_auth_failure! do
# Auth.get(user).login(self)
# end
#
# @raise [ Auth::Unauthorized ] If the authentication failed.
#
# @return [ Object ] The result of the block execution.
#
# @since 2.3.0
def handle_auth_failure!
yield
rescue Auth::Unauthorized
unknown!
raise
end
# Will writes sent to this server be retried.
#
# @example Will writes be retried.
# server.retry_writes?
#
# @return [ true, false ] If writes will be retried.
#
# @note Retryable writes are only available on server versions 3.6+ and with
# sharded clusters or replica sets.
#
# @since 2.5.0
def retry_writes?
!!(features.sessions_enabled? && logical_session_timeout && !standalone?)
end
end
end
|