module Aws::RefreshingCredentials

Base class used credential classes that can be refreshed. This provides basic refresh logic in a thread-safe manner. Classes mixing in this module are expected to implement a refresh method that populates the following instance variables:

@api private

Constants

ASYNC_EXPIRATION_LENGTH
SYNC_EXPIRATION_LENGTH

Public Class Methods

new(options = {}) click to toggle source
# File lib/aws-sdk-core/refreshing_credentials.rb, line 23
def initialize(options = {})
  @mutex = Mutex.new
  @before_refresh = options.delete(:before_refresh) if Hash === options

  @before_refresh.call(self) if @before_refresh
  refresh
end

Public Instance Methods

credentials() click to toggle source

@return [Credentials]

# File lib/aws-sdk-core/refreshing_credentials.rb, line 32
def credentials
  refresh_if_near_expiration!
  @credentials
end
expiration() click to toggle source

@return [Time,nil]

# File lib/aws-sdk-core/refreshing_credentials.rb, line 38
def expiration
  refresh_if_near_expiration!
  @expiration
end
refresh!() click to toggle source

Refresh credentials. @return [void]

# File lib/aws-sdk-core/refreshing_credentials.rb, line 45
def refresh!
  @mutex.synchronize do
    @before_refresh.call(self) if @before_refresh

    refresh
  end
end

Private Instance Methods

near_expiration?(expiration_length) click to toggle source
# File lib/aws-sdk-core/refreshing_credentials.rb, line 84
def near_expiration?(expiration_length)
  if @expiration
    # Are we within expiration?
    (Time.now.to_i + expiration_length) > @expiration.to_i
  else
    true
  end
end
refresh_if_near_expiration!() click to toggle source

Refreshes credentials asynchronously and synchronously. If we are near to expiration, block while getting new credentials. Otherwise, if we're approaching expiration, use the existing credentials but attempt a refresh in the background.

# File lib/aws-sdk-core/refreshing_credentials.rb, line 59
def refresh_if_near_expiration!
  # Note: This check is an optimization. Rather than acquire the mutex on every #refresh_if_near_expiration
  # call, we check before doing so, and then we check within the mutex to avoid a race condition.
  # See issue: https://github.com/aws/aws-sdk-ruby/issues/2641 for more info.
  if near_expiration?(SYNC_EXPIRATION_LENGTH)
    @mutex.synchronize do
      if near_expiration?(SYNC_EXPIRATION_LENGTH)
        @before_refresh.call(self) if @before_refresh
        refresh
      end
    end
  elsif @async_refresh && near_expiration?(ASYNC_EXPIRATION_LENGTH)
    unless @mutex.locked?
      Thread.new do
        @mutex.synchronize do
          if near_expiration?(ASYNC_EXPIRATION_LENGTH)
            @before_refresh.call(self) if @before_refresh
            refresh
          end
        end
      end
    end
  end
end