diff --git a/active_encode.gemspec b/active_encode.gemspec index 66cff4d..327fc19 100644 --- a/active_encode.gemspec +++ b/active_encode.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency "rails" + spec.add_dependency "retriable" spec.add_development_dependency "aws-sdk-cloudwatchevents" spec.add_development_dependency "aws-sdk-cloudwatchlogs" diff --git a/lib/active_encode/engine_adapters/media_convert_adapter.rb b/lib/active_encode/engine_adapters/media_convert_adapter.rb index 2c52298..f43cc49 100644 --- a/lib/active_encode/engine_adapters/media_convert_adapter.rb +++ b/lib/active_encode/engine_adapters/media_convert_adapter.rb @@ -6,6 +6,7 @@ require 'aws-sdk-cloudwatchlogs' require 'aws-sdk-mediaconvert' require 'file_locator' +require 'retriable' require 'active_support/json' require 'active_support/time' @@ -60,6 +61,26 @@ def initialize(msg = nil, encode = nil) end end + class RetriableClient + def initialize + @retry_params = {on: Aws::MediaConvert::Errors::ServiceError, base_interval: 1} + endpoint = Retriable.retriable(@retry_params) { Aws::MediaConvert::Client.new.describe_endpoints.endpoints.first.url } + @client = Aws::MediaConvert::Client.new(endpoint: endpoint) + end + + def method_missing(method, *args, &block) + if @client.respond_to?(method) + Retriable.retriable(@retry_params) { @client.send(method, *args, &block) } + else + super + end + end + + def respond_to?(method) + @client.respond_to?(method) + end + end + attr_accessor :role, :output_bucket attr_writer :log_group, :queue @@ -285,8 +306,7 @@ def cloudwatch_logs end def mediaconvert - endpoint = Aws::MediaConvert::Client.new.describe_endpoints.endpoints.first.url - @mediaconvert ||= Aws::MediaConvert::Client.new(endpoint: endpoint) + @mediaconvert ||= RetriableClient.new end def s3_uri(url, options = {}) diff --git a/spec/integration/media_convert_adapter_spec.rb b/spec/integration/media_convert_adapter_spec.rb index e589eb2..aa9842e 100644 --- a/spec/integration/media_convert_adapter_spec.rb +++ b/spec/integration/media_convert_adapter_spec.rb @@ -176,4 +176,27 @@ def reconstitute_response(fixture_path) end end end + + describe "retry" do + it "recovers from Aws::MediaConvert errors" do + mediaconvert.stub_responses(:get_job, [ + Aws::MediaConvert::Errors::TooManyRequestsException.new(nil, 'Too Many Requests'), + reconstitute_response("media_convert/job_progressing.json") + ]) + expect(ActiveEncode::Base.find(job_id)).to eq(running_job) + end + + it "raises when the retries run out" do + mediaconvert.stub_responses(:get_job, [ + Aws::MediaConvert::Errors::TooManyRequestsException.new(nil, 'Too Many Requests 1'), + Aws::MediaConvert::Errors::TooManyRequestsException.new(nil, 'Too Many Requests 2'), + Aws::MediaConvert::Errors::TooManyRequestsException.new(nil, 'Too Many Requests 3'), + reconstitute_response("media_convert/job_progressing.json") + ]) + expect { ActiveEncode::Base.find(job_id) }.to raise_error do |error| + expect(error).to be_a(Aws::MediaConvert::Errors::TooManyRequestsException) + expect(error.message).to eq('Too Many Requests 3') + end + end + end end