class WebMock::StubRegistry

def register_global_stub(order = :before_local_stubs, &block)

def register_global_stub(order = :before_local_stubs, &block)
  unless %i[before_local_stubs after_local_stubs].include?(order)
    raise ArgumentError.new("Wrong order. Use :before_local_stubs or :after_local_stubs")
  end
  # This hash contains the responses returned by the block,
  # keyed by the exact request (using the object_id).
  # That way, there's no race condition in case #to_return
  # doesn't run immediately after stub.with.
  responses = {}
  response_lock = Mutex.new
  stub = ::WebMock::RequestStub.new(:any, ->(uri) { true }).with { |request|
    update_response = -> { responses[request.object_id] = yield(request) }
    # The block can recurse, so only lock if we don't already own it
    if response_lock.owned?
      update_response.call
    else
      response_lock.synchronize(&update_response)
    end
  }.to_return(lambda { |request|
    response_lock.synchronize { responses.delete(request.object_id) }
  })
  global_stubs[order].push stub
end