Class: Mongo::Retryable::WriteWorker Private
- Inherits:
-
BaseWorker
- Object
- BaseWorker
- Mongo::Retryable::WriteWorker
- Defined in:
- lib/mongo/retryable/write_worker.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Implements the logic around retrying write operations.
Instance Attribute Summary
Attributes inherited from BaseWorker
Instance Method Summary collapse
-
#nro_write_with_retry(_write_concern, context:) {|connection, txn_num, context| ... } ⇒ Object
private
Retryable writes wrapper for operations not supporting modern retryable writes.
-
#retry_write_allowed?(session, write_concern) ⇒ true | false
private
Queries whether the session and write concern support retrying writes.
-
#write_with_retry(write_concern, context:, ending_transaction: false, &block) {|connection, txn_num, context| ... } ⇒ Result
private
Implements write retrying functionality by yielding to the passed block one or more times.
Methods inherited from BaseWorker
Constructor Details
This class inherits a constructor from Mongo::Retryable::BaseWorker
Instance Method Details
#nro_write_with_retry(_write_concern, context:) {|connection, txn_num, context| ... } ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Retryable writes wrapper for operations not supporting modern retryable writes.
If the driver is configured to use modern retryable writes, this method yields to the passed block exactly once, thus not retrying any writes.
If the driver is configured to use legacy retryable writes, this method delegates to legacy_write_with_retry which performs write retries using legacy logic.
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 |
# File 'lib/mongo/retryable/write_worker.rb', line 105 def nro_write_with_retry(_write_concern, context:, &block) session = context.session server = select_server(cluster, ServerSelector.primary, session) = session&.client&. || {} if [:retry_writes] error_count = 0 error_to_raise = nil begin server.with_connection(connection_global_id: context.connection_global_id) do |connection| yield connection, nil, context end rescue Error::TimeoutError raise rescue *retryable_exceptions, Error::PoolError, Error::OperationFailure::Family => e if retryable_overload_error?(e) error_count += 1 error_to_raise ||= e unless e.respond_to?(:label?) && e.label?('NoWritesPerformed') error_to_raise = e end delay = retry_policy.backoff_delay(error_count) raise error_to_raise unless retry_policy.should_retry_overload?(error_count, delay, context: context) log_retry(e, message: 'Write retry (overload backoff)') sleep(delay) begin server = select_server( cluster, ServerSelector.primary, session, server, error: e, timeout: context.remaining_timeout_sec ) rescue Error, Error::AuthError => select_err error_to_raise.add_note("later retry failed: #{select_err.class}: #{select_err}") raise error_to_raise end retry else e.add_note('retries disabled') raise e end end else legacy_write_with_retry(server, context: context, &block) end end |
#retry_write_allowed?(session, write_concern) ⇒ true | false
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Queries whether the session and write concern support retrying writes.
159 160 161 162 163 |
# File 'lib/mongo/retryable/write_worker.rb', line 159 def retry_write_allowed?(session, write_concern) return false unless session&.retry_writes? write_concern.nil? || WriteConcern.get(write_concern).acknowledged? end |
#write_with_retry(write_concern, context:, ending_transaction: false, &block) {|connection, txn_num, context| ... } ⇒ Result
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This only retries operations on not master failures, since it is the only case we can be sure a partial write did not already occur.
Implements write retrying functionality by yielding to the passed block one or more times.
If the session is provided (hence, the deployment supports sessions), and modern retry writes are enabled on the client, the modern retry logic is invoked. Otherwise the legacy retry logic is invoked.
If ending_transaction parameter is true, indicating that a transaction is being committed or aborted, the operation is executed exactly once. Note that, since transactions require sessions, this method will raise ArgumentError if ending_transaction is true and session is nil.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/mongo/retryable/write_worker.rb', line 63 def write_with_retry(write_concern, context:, ending_transaction: false, &block) session = context.session ensure_valid_state!(ending_transaction, session) unless ending_transaction || retry_write_allowed?(session, write_concern) return legacy_write_with_retry(nil, context: context, &block) end # If we are here, session is not nil. A session being nil would have # failed retry_write_allowed? check. server = select_server( cluster, ServerSelector.primary, session, timeout: context.remaining_timeout_sec ) unless ending_transaction || server.retry_writes? return legacy_write_with_retry(server, context: context, &block) end modern_write_with_retry(session, server, context, &block) end |