Module: Mongo::Retryable

Extended by:
Forwardable
Included in:
Cluster::CursorReaper, Collection, Collection::View::Aggregation::Behavior, Collection::View::ChangeStream, Collection::View::MapReduce, Cursor, Database, Database::View, Index::View, SearchIndex::View, Server::Connection, Session
Defined in:
lib/mongo/retryable.rb,
lib/mongo/retryable/base_worker.rb,
lib/mongo/retryable/read_worker.rb,
lib/mongo/retryable/backpressure.rb,
lib/mongo/retryable/retry_policy.rb,
lib/mongo/retryable/write_worker.rb

Overview

Defines basic behavior around retrying operations.

Since:

  • 2.1.0

Defined Under Namespace

Modules: Backpressure Classes: BaseWorker, ReadWorker, RetryPolicy, WriteWorker

Instance Method Summary collapse

Instance Method Details

#read_workerObject

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.

Note:

this is only a public method so that tests can add expectations based on it.

Returns the read worker for handling retryable reads.

Since:

  • 2.1.0



86
87
88
# File 'lib/mongo/retryable.rb', line 86

def read_worker
  @read_worker ||= ReadWorker.new(self)
end

#select_server(cluster, server_selector, session, failed_server = nil, error: nil, timeout: nil) ⇒ Mongo::Server

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 is a separate method to make it possible for the test suite to assert that server selection is performed during retry attempts.

This is a public method so that it can be accessed via the read and write worker delegates, as needed.

Returns:

Since:

  • 2.1.0



49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/mongo/retryable.rb', line 49

def select_server(cluster, server_selector, session, failed_server = nil, error: nil, timeout: nil)
  deprioritized = if failed_server && deprioritize_server?(cluster, error)
                    [ failed_server ]
                  else
                    []
                  end
  server_selector.select_server(
    cluster,
    nil,
    session,
    deprioritized: deprioritized,
    timeout: timeout
  )
end

#with_overload_retry(context: nil, retry_enabled: true) ⇒ 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.

Wraps an operation with overload retry logic. On overload errors (SystemOverloadedError + RetryableError), retries the block with exponential backoff up to MAX_RETRIES times.

The block should include server selection so it is re-done on retry. For cursor operations (getMore), the same server is reused since the cursor is pinned.

Parameters:

  • context (Operation::Context | nil) (defaults to: nil)

    The operation context for CSOT deadline checking.

  • retry_enabled (true | false) (defaults to: true)

    Whether overload retries are permitted. When false, overload errors are raised immediately without retrying (used when retryReads/retryWrites is disabled).

Returns:

  • (Object)

    The result of the block.

Since:

  • 2.1.0



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/mongo/retryable.rb', line 117

def with_overload_retry(context: nil, retry_enabled: true)
  return yield unless retry_enabled

  error_count = 0
  loop do
    result = yield

    return result
  rescue Error::TimeoutError
    raise
  rescue Error::OperationFailure::Family => e
    raise e unless e.label?('SystemOverloadedError') && e.label?('RetryableError')

    error_count += 1
    policy = client.retry_policy
    delay = policy.backoff_delay(error_count)
    raise e unless policy.should_retry_overload?(error_count, delay, context: context)

    Logger.logger.warn("Overload retry due to: #{e.class.name}: #{e.message}")
    sleep(delay)
  end
end

#write_workerObject

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.

Note:

this is only a public method so that tests can add expectations based on it.

Returns the write worker for handling retryable writes.

Since:

  • 2.1.0



96
97
98
# File 'lib/mongo/retryable.rb', line 96

def write_worker
  @write_worker ||= WriteWorker.new(self)
end