File: waiter.rb

package info (click to toggle)
ruby-aws-sdk-core 3.104.3-3%2Bdeb11u2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,444 kB
  • sloc: ruby: 11,201; makefile: 4
file content (134 lines) | stat: -rw-r--r-- 3,988 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
# frozen_string_literal: true

module Aws
  module Waiters
    # @api private
    class Waiter

      # @api private
      RAISE_HANDLER = Seahorse::Client::Plugins::RaiseResponseErrors::Handler

      # @api private
      def initialize(options = {})
        @poller = options[:poller]
        @max_attempts = options[:max_attempts]
        @delay = options[:delay]
        @before_attempt = Array(options[:before_attempt])
        @before_wait = Array(options[:before_wait])
      end

      # @api private
      attr_reader :poller

      # @return [Integer]
      attr_accessor :max_attempts

      # @return [Float]
      attr_accessor :delay

      alias interval delay
      alias interval= delay=

      # Register a callback that is invoked before every polling attempt.
      # Yields the number of attempts made so far.
      #
      #     waiter.before_attempt do |attempts|
      #       puts "#{attempts} made, about to make attempt #{attempts + 1}"
      #     end
      #
      # Throwing `:success` or `:failure` from the given block will stop
      # the waiter and return or raise. You can pass a custom message to the
      # throw:
      #
      #     # raises Aws::Waiters::Errors::WaiterFailed
      #     waiter.before_attempt do |attempts|
      #       throw :failure, 'custom-error-message'
      #     end
      #
      #     # cause the waiter to stop polling and return
      #     waiter.before_attempt do |attempts|
      #       throw :success
      #     end
      #
      # @yieldparam [Integer] attempts The number of attempts made.
      def before_attempt(&block)
        @before_attempt << block if block_given?
      end

      # Register a callback that is invoked after an attempt but before
      # sleeping. Yields the number of attempts made and the previous response.
      #
      #     waiter.before_wait do |attempts, response|
      #       puts "#{attempts} made"
      #       puts response.error.inspect
      #       puts response.data.inspect
      #     end
      #
      # Throwing `:success` or `:failure` from the given block will stop
      # the waiter and return or raise. You can pass a custom message to the
      # throw:
      #
      #     # raises Aws::Waiters::Errors::WaiterFailed
      #     waiter.before_attempt do |attempts|
      #       throw :failure, 'custom-error-message'
      #     end
      #
      #     # cause the waiter to stop polling and return
      #     waiter.before_attempt do |attempts|
      #       throw :success
      #     end
      #
      #
      # @yieldparam [Integer] attempts The number of attempts already made.
      # @yieldparam [Seahorse::Client::Response] response The response from
      #   the previous polling attempts.
      def before_wait(&block)
        @before_wait << block if block_given?
      end

      # @option options [Client] :client
      # @option options [Hash] :params
      def wait(options)
        catch(:success) do
          failure_msg = catch(:failure) do
            return poll(options)
          end
          raise Errors::WaiterFailed.new(failure_msg || 'waiter failed')
        end || true
      end

      private

      def poll(options)
        n = 0
        loop do
          trigger_before_attempt(n)

          state, resp = @poller.call(options)
          n += 1

          case state
          when :retry
          when :success then return resp
          when :failure then raise Errors::FailureStateError.new(resp)
          when :error   then raise Errors::UnexpectedError.new(resp.error)
          end

          raise Errors::TooManyAttemptsError.new(n) if n == @max_attempts

          trigger_before_wait(n, resp)
          sleep(@delay)
        end
      end

      def trigger_before_attempt(attempts)
        @before_attempt.each { |block| block.call(attempts) }
      end

      def trigger_before_wait(attempts, response)
        @before_wait.each { |block| block.call(attempts, response) }
      end

    end
  end
end