We’ve added a feature called Waiters to the v2 AWS SDK for Ruby, and I am pretty excited about it. A waiter is a simple abstraction around the pattern of polling an AWS API until a desired state is reached.
This simple example shows how to use waiters to block until a particular EC2 instance is running:
ec2 = Aws::EC2::Client.new ec2.wait_until(:instance_running, instance_ids:['i-12345678'])
Waiters will not wait indefinitely and can fail. Each waiter has a default polling interval and maximum number of attempts to make. If a waiter encounters an unexpected error or fails to reach the desired condition in time it will raise an error:
begin ec2.wait_until(:instance_running, instance_ids:['i-12345678']) resuce Aws::Waiters::Errors::WaiterFailed # oops end
You can modify the default interval and wait time between attempts by passing a block.
# this will wait upto ~ one hour ec2.wait_until(:instance_running, instance_ids:['i-12345678']) do |w| # seconds between each attempt w.interval = 15 # maximum number of polling attempts before giving up w.max_attempts = 240 end
In addition to interval and maximum attempts, you can configure callbacks to trigger before each attempt polling attempt and before sleeping between attempts.
ec2.wait_until(:instance_running, instance_ids:['i-12345678']) do |w| w.before_attempt do |n| # n - the number of attempts made end w.before_wait do |n, resp| # n - the number of attempts made # resp -the client response from the previous attempt end end
You can throw
:failure from these callbacks to stop the waiter immediately. You can use this to write you own delay and back-off logic.
Here I am using a callback to perform exponential back-off between polling attempts:
ec2.wait_until(:instance_running, instance_ids:['i-12345678']) do |w| w.interval = 0 # disable normal sleep w.before_wait do |n, resp| sleep(n ** 2) end end
This example gives up after one hour.
ec2.wait_until(:instance_running, instance_ids:['i-12345678']) do |w| one_hour_later = Time.now + 3600 w.before_wait do |n, resp| throw :failure, 'waited too long' if Time.now > one_hour_later end end
Waiters and Resources, Looking Ahead
You may have noticed that some waiters have already been exposed to the resource classes.
ec2 = Aws::EC2::Resource.new instance = ec2.instance('i-12345678') instance.stop instance.wait_until_stopped puts instance.id + ' is stopped'
In addition to connecting more waiters and resources, I’m excited to look into batch waiters. Imagine the following use case:
instances = ec2.create_instances(min_count: 5, ...) instances.wait_until_running puts "the following new instances are now running:n" puts instances.map(&:id)
Waiters are documented in the Ruby SDK API reference. Each service client documents the
#wait_until method and provides a list of available waiter names. Here are links to the
Aws::EC2::Client waiter methods:
Give waiters a try and let us know what you think!