mongo 2.14.0 → 2.15.0.alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +4 -1
  5. data/Rakefile +8 -15
  6. data/lib/mongo.rb +23 -0
  7. data/lib/mongo/auth/aws/conversation.rb +1 -4
  8. data/lib/mongo/auth/base.rb +13 -7
  9. data/lib/mongo/auth/conversation_base.rb +32 -0
  10. data/lib/mongo/auth/cr/conversation.rb +6 -29
  11. data/lib/mongo/auth/gssapi/conversation.rb +4 -15
  12. data/lib/mongo/auth/ldap/conversation.rb +3 -14
  13. data/lib/mongo/auth/sasl_conversation_base.rb +1 -13
  14. data/lib/mongo/auth/scram_conversation_base.rb +7 -34
  15. data/lib/mongo/auth/user/view.rb +16 -9
  16. data/lib/mongo/auth/x509/conversation.rb +4 -25
  17. data/lib/mongo/background_thread.rb +11 -0
  18. data/lib/mongo/bulk_write.rb +21 -18
  19. data/lib/mongo/client.rb +82 -6
  20. data/lib/mongo/cluster.rb +19 -28
  21. data/lib/mongo/cluster/reapers/cursor_reaper.rb +6 -2
  22. data/lib/mongo/cluster/sdam_flow.rb +14 -0
  23. data/lib/mongo/collection.rb +8 -6
  24. data/lib/mongo/collection/view/aggregation.rb +1 -1
  25. data/lib/mongo/collection/view/change_stream.rb +1 -1
  26. data/lib/mongo/collection/view/iterable.rb +1 -1
  27. data/lib/mongo/collection/view/map_reduce.rb +2 -2
  28. data/lib/mongo/collection/view/readable.rb +42 -20
  29. data/lib/mongo/collection/view/writable.rb +14 -14
  30. data/lib/mongo/cursor.rb +2 -2
  31. data/lib/mongo/database.rb +22 -5
  32. data/lib/mongo/database/view.rb +1 -1
  33. data/lib/mongo/error.rb +9 -1
  34. data/lib/mongo/error/bulk_write_error.rb +17 -3
  35. data/lib/mongo/error/internal_driver_error.rb +22 -0
  36. data/lib/mongo/error/operation_failure.rb +21 -2
  37. data/lib/mongo/error/parser.rb +65 -12
  38. data/lib/mongo/error/server_api_conflict.rb +23 -0
  39. data/lib/mongo/error/server_api_not_supported.rb +24 -0
  40. data/lib/mongo/error/unmet_dependency.rb +21 -0
  41. data/lib/mongo/grid/fs_bucket.rb +37 -37
  42. data/lib/mongo/index/view.rb +21 -11
  43. data/lib/mongo/monitoring.rb +13 -4
  44. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +27 -16
  45. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +26 -15
  46. data/lib/mongo/operation.rb +2 -2
  47. data/lib/mongo/operation/collections_info.rb +18 -1
  48. data/lib/mongo/operation/collections_info/command.rb +2 -2
  49. data/lib/mongo/operation/context.rb +99 -0
  50. data/lib/mongo/operation/indexes.rb +15 -1
  51. data/lib/mongo/operation/insert/command.rb +2 -2
  52. data/lib/mongo/operation/insert/legacy.rb +2 -2
  53. data/lib/mongo/operation/insert/op_msg.rb +2 -2
  54. data/lib/mongo/operation/list_collections/result.rb +4 -1
  55. data/lib/mongo/operation/result.rb +2 -0
  56. data/lib/mongo/operation/shared/executable.rb +24 -14
  57. data/lib/mongo/operation/shared/executable_no_validate.rb +2 -2
  58. data/lib/mongo/operation/shared/op_msg_or_command.rb +1 -7
  59. data/lib/mongo/operation/shared/op_msg_or_find_command.rb +1 -7
  60. data/lib/mongo/operation/shared/polymorphic_operation.rb +39 -0
  61. data/lib/mongo/operation/shared/response_handling.rb +23 -23
  62. data/lib/mongo/operation/shared/sessions_supported.rb +13 -2
  63. data/lib/mongo/operation/shared/write.rb +8 -18
  64. data/lib/mongo/protocol/compressed.rb +51 -5
  65. data/lib/mongo/protocol/message.rb +20 -2
  66. data/lib/mongo/protocol/msg.rb +36 -11
  67. data/lib/mongo/query_cache.rb +30 -0
  68. data/lib/mongo/retryable.rb +1 -1
  69. data/lib/mongo/server.rb +7 -15
  70. data/lib/mongo/server/app_metadata.rb +52 -18
  71. data/lib/mongo/server/connection.rb +5 -0
  72. data/lib/mongo/server/connection_base.rb +13 -10
  73. data/lib/mongo/server/connection_pool.rb +6 -4
  74. data/lib/mongo/server/description.rb +4 -0
  75. data/lib/mongo/server/description/features.rb +9 -8
  76. data/lib/mongo/server/monitor.rb +20 -1
  77. data/lib/mongo/server/monitor/app_metadata.rb +1 -1
  78. data/lib/mongo/server/monitor/connection.rb +9 -10
  79. data/lib/mongo/server/pending_connection.rb +24 -6
  80. data/lib/mongo/server/push_monitor.rb +11 -1
  81. data/lib/mongo/session.rb +2 -2
  82. data/lib/mongo/session/session_pool.rb +4 -2
  83. data/lib/mongo/socket.rb +29 -4
  84. data/lib/mongo/socket/ssl.rb +8 -0
  85. data/lib/mongo/srv/monitor.rb +0 -11
  86. data/lib/mongo/uri/options_mapper.rb +38 -0
  87. data/lib/mongo/utils.rb +15 -0
  88. data/lib/mongo/version.rb +1 -1
  89. data/spec/README.md +24 -1
  90. data/spec/integration/auth_spec.rb +25 -15
  91. data/spec/integration/bulk_write_error_message_spec.rb +41 -0
  92. data/spec/integration/change_stream_spec.rb +4 -4
  93. data/spec/integration/command_monitoring_spec.rb +2 -2
  94. data/spec/integration/connection_spec.rb +2 -0
  95. data/spec/integration/docs_examples_spec.rb +8 -1
  96. data/spec/integration/fork_reconnect_spec.rb +4 -1
  97. data/spec/integration/ocsp_verifier_spec.rb +13 -7
  98. data/spec/integration/operation_failure_code_spec.rb +1 -1
  99. data/spec/integration/operation_failure_message_spec.rb +90 -0
  100. data/spec/integration/reconnect_spec.rb +1 -1
  101. data/spec/integration/sdam_error_handling_spec.rb +1 -1
  102. data/spec/integration/sdam_events_spec.rb +3 -5
  103. data/spec/integration/snappy_compression_spec.rb +25 -0
  104. data/spec/integration/srv_monitoring_spec.rb +1 -1
  105. data/spec/integration/transactions_examples_spec.rb +6 -0
  106. data/spec/integration/zlib_compression_spec.rb +1 -1
  107. data/spec/integration/zstd_compression_spec.rb +26 -0
  108. data/spec/lite_spec_helper.rb +7 -1
  109. data/spec/mongo/address_spec.rb +15 -11
  110. data/spec/mongo/auth/ldap/conversation_spec.rb +1 -1
  111. data/spec/mongo/auth/ldap_spec.rb +5 -1
  112. data/spec/mongo/auth/scram_negotiation_spec.rb +1 -1
  113. data/spec/mongo/auth/scram_spec.rb +1 -1
  114. data/spec/mongo/auth/x509/conversation_spec.rb +3 -3
  115. data/spec/mongo/client_construction_spec.rb +207 -33
  116. data/spec/mongo/client_spec.rb +17 -0
  117. data/spec/mongo/cluster_spec.rb +3 -18
  118. data/spec/mongo/collection/view/explainable_spec.rb +1 -1
  119. data/spec/mongo/collection/view/readable_spec.rb +33 -19
  120. data/spec/mongo/collection_crud_spec.rb +4357 -0
  121. data/spec/mongo/collection_ddl_spec.rb +534 -0
  122. data/spec/mongo/collection_spec.rb +5 -4859
  123. data/spec/mongo/database_spec.rb +66 -4
  124. data/spec/mongo/error/bulk_write_error_spec.rb +3 -3
  125. data/spec/mongo/error/parser_spec.rb +37 -6
  126. data/spec/mongo/index/view_spec.rb +8 -2
  127. data/spec/mongo/monitoring/event/server_heartbeat_failed_spec.rb +1 -1
  128. data/spec/mongo/monitoring/event/server_heartbeat_succeeded_spec.rb +1 -1
  129. data/spec/mongo/operation/aggregate_spec.rb +2 -1
  130. data/spec/mongo/operation/collections_info_spec.rb +4 -1
  131. data/spec/mongo/operation/command_spec.rb +6 -3
  132. data/spec/mongo/operation/create_index_spec.rb +6 -3
  133. data/spec/mongo/operation/create_user_spec.rb +6 -3
  134. data/spec/mongo/operation/delete/bulk_spec.rb +9 -6
  135. data/spec/mongo/operation/delete_spec.rb +11 -7
  136. data/spec/mongo/operation/drop_index_spec.rb +6 -2
  137. data/spec/mongo/operation/find/legacy_spec.rb +3 -1
  138. data/spec/mongo/operation/get_more_spec.rb +3 -1
  139. data/spec/mongo/operation/indexes_spec.rb +5 -1
  140. data/spec/mongo/operation/insert/bulk_spec.rb +10 -7
  141. data/spec/mongo/operation/insert_spec.rb +15 -12
  142. data/spec/mongo/operation/map_reduce_spec.rb +5 -2
  143. data/spec/mongo/operation/remove_user_spec.rb +6 -3
  144. data/spec/mongo/operation/result_spec.rb +1 -1
  145. data/spec/mongo/operation/update/bulk_spec.rb +9 -6
  146. data/spec/mongo/operation/update_spec.rb +10 -7
  147. data/spec/mongo/operation/update_user_spec.rb +4 -1
  148. data/spec/mongo/protocol/compressed_spec.rb +26 -12
  149. data/spec/mongo/query_cache_middleware_spec.rb +55 -0
  150. data/spec/mongo/retryable_spec.rb +3 -2
  151. data/spec/mongo/server/app_metadata_spec.rb +2 -0
  152. data/spec/mongo/server/connection_pool/populator_spec.rb +3 -1
  153. data/spec/mongo/server/connection_pool_spec.rb +1 -1
  154. data/spec/mongo/server/connection_spec.rb +24 -17
  155. data/spec/mongo/server/monitor/connection_spec.rb +17 -7
  156. data/spec/mongo/server/monitor_spec.rb +9 -1
  157. data/spec/mongo/server_spec.rb +15 -2
  158. data/spec/mongo/socket/ssl_spec.rb +40 -0
  159. data/spec/mongo/socket_spec.rb +2 -2
  160. data/spec/mongo/tls_context_hooks_spec.rb +37 -0
  161. data/spec/runners/connection_string.rb +0 -4
  162. data/spec/runners/crud/requirement.rb +40 -3
  163. data/spec/runners/crud/verifier.rb +8 -0
  164. data/spec/runners/transactions/operation.rb +13 -2
  165. data/spec/runners/transactions/test.rb +1 -0
  166. data/spec/runners/unified.rb +96 -0
  167. data/spec/runners/unified/assertions.rb +249 -0
  168. data/spec/runners/unified/change_stream_operations.rb +26 -0
  169. data/spec/runners/unified/crud_operations.rb +199 -0
  170. data/spec/runners/unified/ddl_operations.rb +96 -0
  171. data/spec/runners/unified/entity_map.rb +39 -0
  172. data/spec/runners/unified/error.rb +25 -0
  173. data/spec/runners/unified/event_subscriber.rb +91 -0
  174. data/spec/runners/unified/exceptions.rb +21 -0
  175. data/spec/runners/unified/grid_fs_operations.rb +55 -0
  176. data/spec/runners/unified/support_operations.rb +250 -0
  177. data/spec/runners/unified/test.rb +393 -0
  178. data/spec/runners/unified/test_group.rb +28 -0
  179. data/spec/runners/unified/using_hash.rb +31 -0
  180. data/spec/shared/bin/get-mongodb-download-url +17 -0
  181. data/spec/shared/lib/mrss/cluster_config.rb +218 -0
  182. data/spec/shared/lib/mrss/constraints.rb +43 -0
  183. data/spec/shared/lib/mrss/docker_runner.rb +262 -0
  184. data/spec/shared/lib/mrss/server_version_registry.rb +112 -0
  185. data/spec/shared/lib/mrss/utils.rb +15 -0
  186. data/spec/shared/share/Dockerfile.erb +231 -0
  187. data/spec/shared/shlib/distro.sh +73 -0
  188. data/spec/shared/shlib/server.sh +290 -0
  189. data/spec/shared/shlib/set_env.sh +128 -0
  190. data/spec/solo/clean_exit_spec.rb +21 -0
  191. data/spec/spec_helper.rb +4 -1
  192. data/spec/spec_tests/crud_unified_spec.rb +10 -0
  193. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
  194. data/spec/spec_tests/data/crud_unified/estimatedDocumentCount.yml +267 -0
  195. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-4.9.yml +60 -0
  196. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount.yml → estimatedDocumentCount-pre4.9.yml} +2 -0
  197. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors-4.9.yml +146 -0
  198. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount-serverErrors.yml → estimatedDocumentCount-serverErrors-pre4.9.yml} +2 -0
  199. data/spec/spec_tests/data/retryable_reads/listIndexNames.yml +1 -1
  200. data/spec/spec_tests/data/unified/valid-fail/operation-failure.yml +31 -0
  201. data/spec/spec_tests/data/unified/valid-pass/poc-change-streams.yml +220 -0
  202. data/spec/spec_tests/data/unified/valid-pass/poc-command-monitoring.yml +102 -0
  203. data/spec/spec_tests/data/unified/valid-pass/poc-crud.yml +184 -0
  204. data/spec/spec_tests/data/unified/valid-pass/poc-gridfs.yml +155 -0
  205. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-reads.yml +193 -0
  206. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-writes.yml +210 -0
  207. data/spec/spec_tests/data/unified/valid-pass/poc-sessions.yml +215 -0
  208. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-convenient-api.yml +235 -0
  209. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-mongos-pin-auto.yml +169 -0
  210. data/spec/spec_tests/data/unified/valid-pass/poc-transactions.yml +170 -0
  211. data/spec/spec_tests/data/uri_options/compression-options.yml +1 -1
  212. data/spec/spec_tests/data/versioned_api/crud-api-version-1-strict.yml +416 -0
  213. data/spec/spec_tests/data/versioned_api/crud-api-version-1.yml +409 -0
  214. data/spec/spec_tests/data/versioned_api/runcommand-helper-no-api-version-declared.yml +67 -0
  215. data/spec/spec_tests/data/versioned_api/test-commands-deprecation-errors.yml +47 -0
  216. data/spec/spec_tests/data/versioned_api/test-commands-strict-mode.yml +44 -0
  217. data/spec/spec_tests/data/versioned_api/transaction-handling.yml +180 -0
  218. data/spec/spec_tests/unified_spec.rb +15 -0
  219. data/spec/spec_tests/uri_options_spec.rb +16 -0
  220. data/spec/spec_tests/versioned_api_spec.rb +10 -0
  221. data/spec/support/common_shortcuts.rb +15 -1
  222. data/spec/support/shared/session.rb +2 -2
  223. data/spec/support/spec_config.rb +46 -3
  224. data/spec/support/spec_setup.rb +48 -38
  225. data/spec/support/utils.rb +64 -3
  226. metadata +1104 -992
  227. metadata.gz.sig +0 -0
  228. data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +0 -58
  229. data/lib/mongo/operation/shared/op_msg_or_list_indexes_command.rb +0 -47
  230. data/spec/support/cluster_config.rb +0 -207
@@ -63,6 +63,11 @@ module Mongo
63
63
  end
64
64
 
65
65
  result = handshake!(speculative_auth_doc: speculative_auth_doc)
66
+
67
+ if description.unknown?
68
+ raise Error::InternalDriverError, "Connection description cannot be unknown after successful handshake: #{description.inspect}"
69
+ end
70
+
66
71
  if speculative_auth_doc && (speculative_auth_result = result['speculativeAuthenticate'])
67
72
  unless description.features.scram_sha_1_enabled?
68
73
  raise Error::InvalidServerAuthResponse, "Speculative auth succeeded on a pre-3.0 server"
@@ -80,11 +85,15 @@ module Mongo
80
85
  speculative_auth_result: speculative_auth_result,
81
86
  )
82
87
  else
83
- raise NotImplementedError, "Speculative auth unexpectedly succeeded for mechanism #{speculative_auth_user.mechanism.inspect}"
88
+ raise Error::InternalDriverError, "Speculative auth unexpectedly succeeded for mechanism #{speculative_auth_user.mechanism.inspect}"
84
89
  end
85
90
  elsif !description.arbiter?
86
91
  authenticate!
87
92
  end
93
+
94
+ if description.unknown?
95
+ raise Error::InternalDriverError, "Connection description cannot be unknown after successful authentication: #{description.inspect}"
96
+ end
88
97
  end
89
98
 
90
99
  private
@@ -96,7 +105,7 @@ module Mongo
96
105
  # this particular connection.
97
106
  def handshake!(speculative_auth_doc: nil)
98
107
  unless socket
99
- raise Error::HandshakeError, "Cannot handshake because there is no usable socket (for #{address})"
108
+ raise Error::InternalDriverError, "Cannot handshake because there is no usable socket (for #{address})"
100
109
  end
101
110
 
102
111
  ismaster_doc = app_metadata.validated_document
@@ -104,18 +113,27 @@ module Mongo
104
113
  ismaster_doc = ismaster_doc.merge(speculativeAuthenticate: speculative_auth_doc)
105
114
  end
106
115
 
116
+ if server_api = options[:server_api]
117
+ ismaster_doc = ismaster_doc.merge(
118
+ Utils.transform_server_api(server_api)
119
+ )
120
+ end
121
+
107
122
  ismaster_command = Protocol::Query.new(Database::ADMIN, Database::COMMAND,
108
123
  ismaster_doc, :limit => -1)
109
124
 
110
- response = nil
125
+ doc = nil
111
126
  @server.handle_handshake_failure! do
112
127
  begin
113
128
  response = @server.round_trip_time_averager.measure do
114
129
  add_server_diagnostics do
115
130
  socket.write(ismaster_command.serialize.to_s)
116
- Protocol::Message.deserialize(socket, Protocol::Message::MAX_MESSAGE_SIZE).documents.first
131
+ Protocol::Message.deserialize(socket, Protocol::Message::MAX_MESSAGE_SIZE)
117
132
  end
118
133
  end
134
+ result = Operation::Result.new([response])
135
+ result.validate!
136
+ doc = result.documents.first
119
137
  rescue => exc
120
138
  msg = "Failed to handshake with #{address}"
121
139
  Utils.warn_bg_exception(msg, exc,
@@ -127,9 +145,9 @@ module Mongo
127
145
  end
128
146
  end
129
147
 
130
- post_handshake(response, @server.round_trip_time_averager.average_round_trip_time)
148
+ post_handshake(doc, @server.round_trip_time_averager.average_round_trip_time)
131
149
 
132
- response
150
+ doc
133
151
  end
134
152
 
135
153
  # @param [ String | nil ] speculative_auth_client_nonce The client
@@ -33,6 +33,9 @@ module Mongo
33
33
  if topology_version.nil?
34
34
  raise ArgumentError, 'Topology version must be provided but it was nil'
35
35
  end
36
+ unless options[:app_metadata]
37
+ raise ArgumentError, 'App metadata is required'
38
+ end
36
39
  @monitor = monitor
37
40
  @topology_version = topology_version
38
41
  @monitoring = monitoring
@@ -139,7 +142,9 @@ module Mongo
139
142
  raise
140
143
  end
141
144
  @server_pushing = resp_msg.flags.include?(:more_to_come)
142
- result = resp_msg.documents.first
145
+ result = Operation::Result.new(resp_msg)
146
+ result.validate!
147
+ result.documents.first
143
148
  end
144
149
 
145
150
  def write_ismaster
@@ -147,6 +152,11 @@ module Mongo
147
152
  topologyVersion: topology_version.to_doc,
148
153
  maxAwaitTimeMS: monitor.heartbeat_interval * 1000,
149
154
  )
155
+ if server_api = options[:server_api]
156
+ payload.update(
157
+ Utils.transform_server_api(server_api)
158
+ )
159
+ end
150
160
 
151
161
  req_msg = Protocol::Msg.new([:exhaust_allowed], {}, payload)
152
162
  @lock.synchronize { @connection }.write_bytes(req_msg.serialize.to_s)
data/lib/mongo/session.rb CHANGED
@@ -582,7 +582,7 @@ module Mongo
582
582
  txn_num: txn_num,
583
583
  write_concern: write_concern,
584
584
  }
585
- Operation::Command.new(spec).execute(server, client: @client)
585
+ Operation::Command.new(spec).execute(server, context: Operation::Context.new(client: @client, session: self))
586
586
  end
587
587
  end
588
588
  ensure
@@ -629,7 +629,7 @@ module Mongo
629
629
  db_name: 'admin',
630
630
  session: self,
631
631
  txn_num: txn_num
632
- ).execute(server, client: @client)
632
+ ).execute(server, context: Operation::Context.new(client: @client, session: self))
633
633
  end
634
634
  end
635
635
 
@@ -119,8 +119,10 @@ module Mongo
119
119
  },
120
120
  db_name: Database::ADMIN,
121
121
  )
122
- # end_sessions does not take a client as an argument
123
- op.execute(server, client: nil)
122
+ context = Operation::Context.new(options: {
123
+ server_api: server.options[:server_api],
124
+ })
125
+ op.execute(server, context: context)
124
126
  end
125
127
  rescue Mongo::Error, Error::AuthError
126
128
  end
data/lib/mongo/socket.rb CHANGED
@@ -30,6 +30,7 @@ module Mongo
30
30
  # Error message for TLS related exceptions.
31
31
  #
32
32
  # @since 2.0.0
33
+ # @deprecated
33
34
  SSL_ERROR = 'MongoDB may not be configured with TLS support'.freeze
34
35
 
35
36
  # Error message for timeouts on socket calls.
@@ -154,7 +155,14 @@ module Mongo
154
155
  #
155
156
  # @since 2.0.0
156
157
  def close
157
- @socket.close rescue nil
158
+ begin
159
+ # Sometimes it seems the close call can hang for a long time
160
+ ::Timeout.timeout(5) do
161
+ @socket.close
162
+ end
163
+ rescue
164
+ # Silence all errors
165
+ end
158
166
  true
159
167
  end
160
168
 
@@ -326,8 +334,21 @@ module Mongo
326
334
  else
327
335
  select_args = [nil, [@socket], [@socket], select_timeout]
328
336
  end
329
- unless Kernel::select(*select_args)
330
- raise Errno::ETIMEDOUT, "Took more than #{_timeout} seconds to receive data"
337
+ rv = Kernel.select(*select_args)
338
+ if BSON::Environment.jruby?
339
+ # Ignore the return value of Kernel.select.
340
+ # On JRuby, select appears to return nil prior to timeout expiration
341
+ # (apparently due to a EAGAIN) which then causes us to fail the read
342
+ # even though we could have retried it.
343
+ # Check the deadline ourselves.
344
+ if deadline
345
+ select_timeout = deadline - Time.now
346
+ if select_timeout <= 0
347
+ raise Errno::ETIMEDOUT, "Took more than #{_timeout} seconds to receive data"
348
+ end
349
+ end
350
+ elsif rv.nil?
351
+ raise Errno::ETIMEDOUT, "Took more than #{_timeout} seconds to receive data (select call timed out)"
331
352
  end
332
353
  retry
333
354
  end
@@ -398,6 +419,10 @@ module Mongo
398
419
  set_option(sock, :TCP_KEEPCNT, DEFAULT_TCP_KEEPCNT)
399
420
  set_option(sock, :TCP_KEEPIDLE, DEFAULT_TCP_KEEPIDLE)
400
421
  rescue
422
+ # JRuby 9.2.13.0 and lower do not define TCP_KEEPINTVL etc. constants.
423
+ # JRuby 9.2.14.0 defines the constants but does not allow to get or
424
+ # set them with this error:
425
+ # Errno::ENOPROTOOPT: Protocol not available - Protocol not available
401
426
  end
402
427
 
403
428
  def set_option(sock, option, default)
@@ -422,7 +447,7 @@ module Mongo
422
447
  rescue IOError, SystemCallError => e
423
448
  raise Error::SocketError, "#{e.class}: #{e} (for #{human_address})"
424
449
  rescue OpenSSL::SSL::SSLError => e
425
- raise Error::SocketError, "#{e.class}: #{e} (for #{human_address}) (#{SSL_ERROR})"
450
+ raise Error::SocketError, "#{e.class}: #{e} (for #{human_address})"
426
451
  end
427
452
  end
428
453
 
@@ -106,6 +106,8 @@ module Mongo
106
106
  begin
107
107
  @tcp_socket.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1)
108
108
  set_socket_options(@tcp_socket)
109
+ run_tls_context_hooks
110
+
109
111
  connect!
110
112
  rescue
111
113
  @tcp_socket.close
@@ -379,6 +381,12 @@ module Mongo
379
381
  def human_address
380
382
  "#{host}:#{port} (#{host_name}:#{port}, TLS)"
381
383
  end
384
+
385
+ def run_tls_context_hooks
386
+ Mongo.tls_context_hooks.each do |hook|
387
+ hook.call(@context)
388
+ end
389
+ end
382
390
  end
383
391
  end
384
392
  end
@@ -59,11 +59,6 @@ module Mongo
59
59
  # records' TTL values.
60
60
  attr_reader :last_result
61
61
 
62
- def start!
63
- super
64
- ObjectSpace.define_finalizer(self, self.class.finalize(@thread))
65
- end
66
-
67
62
  private
68
63
 
69
64
  def do_work
@@ -97,12 +92,6 @@ module Mongo
97
92
  @cluster.set_server_list(last_result.address_strs)
98
93
  end
99
94
 
100
- def self.finalize(thread)
101
- Proc.new do
102
- thread.kill
103
- end
104
- end
105
-
106
95
  def scan_interval
107
96
  if last_result.empty?
108
97
  [cluster.heartbeat_interval, MIN_SCAN_INTERVAL].min
@@ -82,6 +82,44 @@ module Mongo
82
82
  end
83
83
  end
84
84
 
85
+ def smc_to_ruby(opts)
86
+ uri_options = {}
87
+
88
+ opts.each do |key, value|
89
+ strategy = URI_OPTION_MAP[key.downcase]
90
+ if strategy.nil?
91
+ log_warn("Unsupported URI option '#{key}' on URI '#{@string}'. It will be ignored.")
92
+ return
93
+ end
94
+
95
+ group = strategy[:group]
96
+ target = if group
97
+ uri_options[group] || {}
98
+ else
99
+ uri_options
100
+ end
101
+
102
+ if key == 'readConcernLevel'
103
+ value = value.to_sym
104
+ end
105
+
106
+ #value = apply_transform(key, value, strategy[:type])
107
+ # Sometimes the value here would be nil, for example if we are processing
108
+ # read preference tags or auth mechanism properties and all of the
109
+ # data within is invalid. Ignore such options.
110
+ unless value.nil?
111
+ merge_uri_option(target, value, strategy[:name])
112
+ end
113
+
114
+ if group && !target.empty? && !uri_options.key?(group)
115
+ uri_options[group] = target
116
+ end
117
+ end
118
+
119
+ #p uri_options
120
+ uri_options
121
+ end
122
+
85
123
  # Converts Ruby options provided to "standardized MongoClient options".
86
124
  #
87
125
  # @param [ Hash ] opts Ruby options to convert.
data/lib/mongo/utils.rb CHANGED
@@ -69,5 +69,20 @@ module Mongo
69
69
  module_function def camelize(sym)
70
70
  sym.to_s.gsub(/_(\w)/) { $1.upcase }
71
71
  end
72
+
73
+ # @note server_api must have symbol keys or be a BSON::Document.
74
+ module_function def transform_server_api(server_api)
75
+ {}.tap do |doc|
76
+ if version = server_api[:version]
77
+ doc['apiVersion'] = version
78
+ end
79
+ unless server_api[:strict].nil?
80
+ doc['apiStrict'] = server_api[:strict]
81
+ end
82
+ unless server_api[:deprecation_errors].nil?
83
+ doc['apiDeprecationErrors'] = server_api[:deprecation_errors]
84
+ end
85
+ end
86
+ end
72
87
  end
73
88
  end
data/lib/mongo/version.rb CHANGED
@@ -17,5 +17,5 @@ module Mongo
17
17
  # The current version of the driver.
18
18
  #
19
19
  # @since 2.0.0
20
- VERSION = '2.14.0'.freeze
20
+ VERSION = '2.15.0.alpha'.freeze
21
21
  end
data/spec/README.md CHANGED
@@ -512,13 +512,36 @@ To test compression, set the `compressors` URI option:
512
512
 
513
513
  MONGODB_URI="mongodb://localhost:27017/?compressors=zlib" rake
514
514
 
515
- Note that as of this writing, the driver only supports zlib compression.
515
+ Note that as of this writing, the driver supports
516
+ [ztsd](https://docs.mongodb.com/manual/reference/glossary/#term-zstd),
517
+ [snappy](https://docs.mongodb.com/manual/reference/glossary/#term-snappy)
518
+ and [zlib](https://docs.mongodb.com/manual/reference/glossary/#term-zlib)
519
+ compression.
520
+
516
521
  Servers 4.2+ enable zlib by default; to test older servers, explicitly enable
517
522
  zlib compression when launching the server:
518
523
 
519
524
  mongod --dbpath /tmp/mdb --setParameter enableTestCommands=1 \
520
525
  --networkMessageCompressors snappy,zlib
521
526
 
527
+ ## Server API
528
+
529
+ To specify server API parameters, use the `SERVER_API` environment variable.
530
+ The server API parameters cannot be specified via URI options.
531
+
532
+ Both YAML and JSON syntaxes are accepted:
533
+
534
+ SERVER_API='{version: "1", strict: true}' rake
535
+
536
+ SERVER_API='{"version":"1","strict":true}' rake
537
+
538
+ Note that the input must be valid YAML or JSON and the version number must
539
+ be a string, therefore all of the following specifications are invalid:
540
+
541
+ SERVER_API='{version:"1",strict:true}' rake
542
+ SERVER_API='{version: 1}' rake
543
+ SERVER_API='{"version":1,"strict":true}' rake
544
+
522
545
  ## Other Options
523
546
 
524
547
  Generally, all URI options recognized by the driver may be set for a test run,
@@ -10,8 +10,12 @@ describe 'Auth' do
10
10
  authorized_client.cluster.next_primary
11
11
  end
12
12
 
13
+ let(:base_options) do
14
+ SpecConfig.instance.monitoring_options
15
+ end
16
+
13
17
  let(:connection) do
14
- Mongo::Server::Connection.new(server, options)
18
+ Mongo::Server::Connection.new(server, base_options.merge(options))
15
19
  end
16
20
 
17
21
  before(:all) do
@@ -31,8 +35,9 @@ describe 'Auth' do
31
35
  context 'user mechanism not provided' do
32
36
 
33
37
  context 'user does not exist' do
34
- let(:options) { SpecConfig.instance.ssl_options.merge(
35
- user: 'nonexistent_user') }
38
+ let(:options) do
39
+ {user: 'nonexistent_user' }
40
+ end
36
41
 
37
42
  before do
38
43
  expect(connection.app_metadata.send(:document)[:saslSupportedMechs]).to eq('admin.nonexistent_user')
@@ -63,8 +68,9 @@ describe 'Auth' do
63
68
  end
64
69
 
65
70
  context 'user exists' do
66
- let(:options) { SpecConfig.instance.ssl_options.merge(
67
- user: 'existing_user', password: 'bogus') }
71
+ let(:options) do
72
+ {user: 'existing_user', password: 'bogus'}
73
+ end
68
74
 
69
75
  before do
70
76
  expect(connection.app_metadata.send(:document)[:saslSupportedMechs]).to eq("admin.existing_user")
@@ -99,8 +105,9 @@ describe 'Auth' do
99
105
  min_server_fcv '3.0'
100
106
 
101
107
  context 'scram-sha-1 requested' do
102
- let(:options) { SpecConfig.instance.ssl_options.merge(
103
- user: 'nonexistent_user', auth_mech: :scram) }
108
+ let(:options) do
109
+ {user: 'nonexistent_user', auth_mech: :scram}
110
+ end
104
111
 
105
112
  it 'indicates scram-sha-1 was requested and used' do
106
113
  expect do
@@ -112,8 +119,9 @@ describe 'Auth' do
112
119
  context 'scram-sha-256 requested' do
113
120
  min_server_fcv '4.0'
114
121
 
115
- let(:options) { SpecConfig.instance.ssl_options.merge(
116
- user: 'nonexistent_user', auth_mech: :scram256) }
122
+ let(:options) do
123
+ {user: 'nonexistent_user', auth_mech: :scram256}
124
+ end
117
125
 
118
126
  it 'indicates scram-sha-256 was requested and used' do
119
127
  expect do
@@ -124,8 +132,9 @@ describe 'Auth' do
124
132
  end
125
133
 
126
134
  context 'when authentication fails' do
127
- let(:options) { SpecConfig.instance.ssl_options.merge(
128
- user: 'nonexistent_user', password: 'foo') }
135
+ let(:options) do
136
+ {user: 'nonexistent_user', password: 'foo'}
137
+ end
129
138
 
130
139
  it 'reports which server authentication was attempted against' do
131
140
  expect do
@@ -142,8 +151,9 @@ describe 'Auth' do
142
151
  end
143
152
 
144
153
  context 'with custom auth source' do
145
- let(:options) { SpecConfig.instance.ssl_options.merge(
146
- user: 'nonexistent_user', password: 'foo', auth_source: 'authdb') }
154
+ let(:options) do
155
+ {user: 'nonexistent_user', password: 'foo', auth_source: 'authdb'}
156
+ end
147
157
 
148
158
  it 'reports auth source used' do
149
159
  expect do
@@ -240,7 +250,7 @@ describe 'Auth' do
240
250
  require_no_auth
241
251
 
242
252
  let(:client) do
243
- new_local_client(SpecConfig.instance.addresses, SpecConfig.instance.ssl_options.merge(
253
+ new_local_client(SpecConfig.instance.addresses, SpecConfig.instance.monitoring_options.merge(
244
254
  auth_source: 'foo'))
245
255
  end
246
256
 
@@ -254,7 +264,7 @@ describe 'Auth' do
254
264
  require_x509_auth
255
265
 
256
266
  let(:client) do
257
- new_local_client(SpecConfig.instance.addresses, SpecConfig.instance.ssl_options.merge(
267
+ new_local_client(SpecConfig.instance.addresses, base_options.merge(
258
268
  auth_mech: :mongodb_x509))
259
269
  end
260
270