class OCI::Response

A response, which represents all successful API calls.

Adds to the Response class in lib/oci/response.rb to define wait behavior

Attributes

api_call[W]
data[R]

The body of the response. For example, this may contain a User object, or a list of Users.

headers[R]

A ResponseHeaders object containing all response headers

@return [ResponseHeaders]

next_page[R]

The value of the next page token, if available, taken from the opc-next-page header.

@return [String]

request_id[R]

The request ID, taken from the opc-request-id header.

@return [String]

status[R]

The HTTP status, such as 200, 401, etc

@return [Integer]

Public Class Methods

new(status, headers, data) click to toggle source
# File lib/oci/response.rb, line 34
def initialize(status, headers, data)
  @status = status
  @headers = OCI::ResponseHeaders.new(headers)
  @data = data

  @next_page = @headers['opc-next-page'] if headers
  @next_page = data.next_start_with if data.is_a?(OCI::ObjectStorage::Models::ListObjects)
  @request_id = @headers['opc-request-id'] if headers
end

Public Instance Methods

each() { |self| ... } click to toggle source

For paged responses, yields each page until the last page is reached. For example:

OCI::Identity::IdentityClient.new.list_users(compartment, limit:'3').each { |r| r.data.each { |user| puts user.name }}

The first response yielded is always the response that 'each' is being called on.

If any of the requests result in an error, that error will be thrown as normal, which will abort the enumeration.

While this can be called on non-paged responses, it will simply result in the response itself being yielded.

@yieldparam [Response] response A response object for each page, starting with the response used to call 'each'.

# File lib/oci/response.rb, line 66
def each
  yield self
  page = @next_page

  while @api_call && page
    next_response = @api_call.call(page)

    raise 'Paging failure: Two consecutive responses had the same next page token.' if page == next_response.next_page

    page = next_response.next_page
    yield next_response
  end
end
has_next_page?() click to toggle source

Returns true if there is another page available.

# File lib/oci/response.rb, line 45
def has_next_page?
  !next_page.nil?
end
wait_until( property = nil, state = nil, eval_proc: nil, max_interval_seconds: 30, max_wait_seconds: 1200, succeed_on_not_found: false ) { |response| ... } click to toggle source

Wait until the value of the given property in the response data has the given value. This will block the current thread until the the desired state is reached, the maximum wait time is reached, or the optional yield block throws :stop_succeed or :stop_fail. This is only supported for responses resulting from GET operations. A typical use case is to wait on an instance until it is in a running state:

compute_client.get_instance(@instance_id).wait_until(:lifecycle_state, OCI::Core::Models::Instance::LIFECYCLE_STATE_RUNNING)

Although this can be run on any property of the data resulting from any GET operation, the most common use case is to check state properties on operations that GET a single object.

The wait will poll at an increasing interval up to 'max_interval_seconds' for a maximum total time of 'max_wait_seconds'. If the maximum time is exceeded, then it will raise a {OCI::Waiter::Errors::MaximumWaitTimeExceededError}.

On successful completion the final Response object will be returned. The original Response object will not be altered.

If any responses result in an error, then the error will be thrown as normal resulting in the wait being aborted.

@param [Symbol] property The property of the response data to evaluate. For example, :lifecycle_state. @param state The value of the property that will indicate successful completion of the wait. @param [Proc] eval_proc A proc/lambda which can be fed a response from a GET operation and evaluate whether a waiter should return

or keep checking. This can be used for logic which extends beyond checking equality of a single attribute, for example checking
that an attribute is one of a possible set of values. If an eval_proc is specified, then neither a property nor state can
be specified. The result of the proc/lambda should be truthy if the waiter should stop waiting, and falsey otherwise.

@param [Integer] max_interval_seconds The maximum interval between queries, in seconds. @param [Integer] max_wait_seconds The maximum time to wait, in seconds. @param [boolean] succeed_on_not_found A boolean determining whether or not the waiter should return successfully if the data we're waiting on is not found (e.g. a 404 is

returned from the service). This defaults to false and so a 404 would cause an exception to be thrown by this function. Setting it to true may be useful
in scenarios when waiting for a resource to be terminated/deleted since it is possible that the resource would not be returned by the a GET call anymore.

@yieldparam [Response] response A response object for every additional successful call to the get request.

Throw :stop_succeed from the yield to stop the waiter and return the current response.
Throw :stop_fail from the yield to stop the waiter and throw a WaiterFailedError.

@return [Response] The final response, which will contain the property in the specified state.

# File lib/oci/waiter.rb, line 109
def wait_until(
  property = nil,
  state = nil,
  eval_proc: nil,
  max_interval_seconds: 30,
  max_wait_seconds: 1200,
  succeed_on_not_found: false
)
  raise 'Cannot wait on a response without data.' unless data
  raise 'Either an eval_proc or a property and response must be specified' if !eval_proc && property.nil? && state.nil?
  raise 'Cannot specify both an eval_proc and a property or state' if eval_proc && (!property.nil? || !state.nil?)
  raise 'If a property is specified, then a state must also be specified' if !eval_proc && (property.nil? || state.nil?)
  raise 'Response data does not contain the given property.' if property && !data.methods.include?(property)

  raise Waiter::Errors::WaitUntilNotSupportedError, 'wait_until is not supported by this response.' unless @api_call

  response = self
  interval_seconds = 1
  start_time = Time.now

  loop do
    return response if !property.nil? && response.data.send(property) == state
    return response if eval_proc && eval_proc.call(response)

    elapsed_seconds = (Time.now - start_time).to_i

    if elapsed_seconds + interval_seconds > max_wait_seconds
      raise Waiter::Errors::MaximumWaitTimeExceededError, 'Maximum wait time has been exceeded.' \
        unless max_wait_seconds > elapsed_seconds

      # Make one last request right at the maximum wait time.
      interval_seconds = max_wait_seconds - elapsed_seconds
    end

    sleep(interval_seconds)

    interval_seconds *= 2
    interval_seconds = max_interval_seconds if interval_seconds > max_interval_seconds

    begin
      response = @api_call.call(nil)
      response.api_call = @api_call
    rescue OCI::Errors::ServiceError => e
      return nil if e.status_code == 404 && succeed_on_not_found

      raise
    end

    next unless block_given?

    continue = false
    catch(:stop_fail) do
      catch(:stop_succeed) do
        yield response
        continue = true
      end

      return response unless continue
    end

    raise Waiter::Errors::WaiterFailedError unless continue
  end
end