Skip to content

Commit

Permalink
Merge pull request #132 from plivo/VT-1545
Browse files Browse the repository at this point in the history
Voice retry logic part for Ruby SDK
  • Loading branch information
nixonsam authored Aug 5, 2020
2 parents 2e673c2 + c7aed4d commit 0a02957
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 40 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Change Log

## [4.9.0](https://github.com/plivo/plivo-ruby/releases/tag/v4.9.0) (2020-07-23)
- Add retries to multiple regions for voice requests.

## [4.8.1](https://github.com/plivo/plivo-ruby/releases/tag/v4.8.1) (2020-06-05)
- Fix Record a Conference API response.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The Plivo Ruby SDK makes it simpler to integrate communications into your Ruby a
Add this line to your application's Gemfile:

```ruby
gem 'plivo', '>= 4.8.1'
gem 'plivo', '>= 4.9.0'
```

And then execute:
Expand Down
5 changes: 5 additions & 0 deletions lib/plivo/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
module Plivo
module Base
PLIVO_API_URL = 'https://api.plivo.com'.freeze

API_VOICE = 'https://voice.plivo.com'.freeze
API_VOICE_FALLBACK_1 = 'https://voice-usw1.plivo.com'.freeze
API_VOICE_FALLBACK_2 = 'https://voice-use1.plivo.com'.freeze

CALLINSIGHTS_API_URL = 'https://stats.plivo.com'.freeze
PHLO_API_URL = 'https://phlorunner.plivo.com'.freeze
end
Expand Down
15 changes: 8 additions & 7 deletions lib/plivo/base/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def initialize(client, options = nil)
configure_client(client)
configure_options(options) if options
configure_resource_uri
@_is_voice_request = false
end

private
Expand Down Expand Up @@ -56,7 +57,7 @@ def perform_update(params, use_multipart_conn = false)
'without an identifier')
end

response_json = @_client.send_request(@_resource_uri, 'POST', params, nil, use_multipart_conn)
response_json = @_client.send_request(@_resource_uri, 'POST', params, nil, use_multipart_conn, is_voice_request: @_is_voice_request)

parse_and_set(params)
parse_and_set(response_json)
Expand All @@ -65,23 +66,23 @@ def perform_update(params, use_multipart_conn = false)

def perform_action(action = nil, method = 'GET', params = nil, parse = false)
resource_path = action ? @_resource_uri + action + '/' : @_resource_uri
response = @_client.send_request(resource_path, method, params)
response = @_client.send_request(resource_path, method, params,nil,false,is_voice_request: @_is_voice_request)
parse ? parse_and_set(response) : self
method == 'POST' ? parse_and_set(params) : self
self
end

def perform_custome_action(action = nil, method = 'GET', params = nil, parse = false)
resource_path = action ? @_resource_uri + action + '/' : @_resource_uri
response = @_client.send_request(resource_path, method, params)
response = @_client.send_request(resource_path, method, params,nil,false,is_voice_request: @_is_voice_request)
parse ? parse_and_set(response) : self
method == 'POST' ? parse_and_set(params) : self
self
end

def perform_action_apiresponse(action = nil, method = 'GET', params = nil, parse = false)
resource_path = action ? @_resource_uri + action + '/' : @_resource_uri
response = @_client.send_request(resource_path, method, params)
response = @_client.send_request(resource_path, method, params,nil,false,is_voice_request: @_is_voice_request)
parse ? parse_and_set(response) : self
method == 'POST' ? parse_and_set(params) : self
method == 'DELETE' ? parse_and_set(params) : self
Expand All @@ -90,7 +91,7 @@ def perform_action_apiresponse(action = nil, method = 'GET', params = nil, parse

def perform_custom_action_apiresponse(action = nil, method = 'GET', params = nil, parse = false)
resource_path = action ? '/v1/Account/' + @_client.auth_id + '/'+ action + '/' : @_resource_uri
response = @_client.send_request(resource_path, method, params)
response = @_client.send_request(resource_path, method, params,nil,false,is_voice_request: @_is_voice_request)
parse ? parse_and_set(response) : self
method == 'POST' ? parse_and_set(params) : self
method == 'DELETE' ? parse_and_set(params) : self
Expand All @@ -103,12 +104,12 @@ def perform_delete(params=nil)
'without an identifier')
end

Response.new(@_client.send_request(@_resource_uri, 'DELETE', params),
Response.new(@_client.send_request(@_resource_uri, 'DELETE', params, nil, false, is_voice_request: @_is_voice_request),
@_identifier_string)
end

def perform_run(params)
response_json = @_client.send_request(@_resource_uri, 'POST', params, nil)
response_json = @_client.send_request(@_resource_uri, 'POST', params, nil,false,is_voice_request: @_is_voice_request)
parse_and_set(response_json)
Response.new(response_json, @_identifier_string)
end
Expand Down
15 changes: 8 additions & 7 deletions lib/plivo/base/resource_interface.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ def initialize(client, resource_list_json = nil)
configure_client(client)
configure_resource_uri
parse_and_set(resource_list_json) if resource_list_json
@_is_voice_request = false
end

private
Expand Down Expand Up @@ -41,25 +42,25 @@ def parse_and_set(resource_list_json)

def perform_get(identifier, params = nil)
valid_param?(:identifier, identifier, [String, Symbol], true)
response_json = @_client.send_request(@_resource_uri + identifier.to_s + '/', 'GET', params)
response_json = @_client.send_request(@_resource_uri + identifier.to_s + '/', 'GET', params, nil, false, is_voice_request: @_is_voice_request)
@_resource_type.new(@_client, resource_json: response_json)
end

def perform_get_without_identifier(params)
valid_param?(:params, params, Hash, true)
response_json = @_client.send_request(@_resource_uri, 'GET', params)
response_json = @_client.send_request(@_resource_uri, 'GET', params, nil, false, is_voice_request: @_is_voice_request)
@_resource_type.new(@_client, resource_json: response_json)
end

def perform_create(params, use_multipart_conn=false)
Response.new(
@_client.send_request(@_resource_uri, 'POST', params, nil, use_multipart_conn),
@_client.send_request(@_resource_uri, 'POST', params, nil, use_multipart_conn, is_voice_request: @_is_voice_request),
@_identifier_string
)
end

def perform_post(params)
response_json = @_client.send_request(@_resource_uri, 'POST', params)
response_json = @_client.send_request(@_resource_uri, 'POST', params, nil, false, is_voice_request: @_is_voice_request)

parse_and_set(response_json)
self
Expand All @@ -74,7 +75,7 @@ def parse_and_set_list(list_json)
end

def perform_list(params = nil)
response_json = @_client.send_request(@_resource_uri, 'GET', params)
response_json = @_client.send_request(@_resource_uri, 'GET', params, nil, false, is_voice_request: @_is_voice_request)
parse_and_set(response_json)
{
api_id: @api_id,
Expand All @@ -85,14 +86,14 @@ def perform_list(params = nil)

def perform_action(action = nil, method = 'GET', params = nil, parse = false)
resource_path = action ? @_resource_uri + action + '/' : @_resource_uri
response = @_client.send_request(resource_path, method, params)
response = @_client.send_request(resource_path, method, params, nil, false, is_voice_request: @_is_voice_request)
parse ? parse_and_set(response) : self
method == 'POST' ? parse_and_set(params) : self
self
end

def perform_list_without_object(params = nil)
response_json = @_client.send_request(@_resource_uri, 'GET', params)
response_json = @_client.send_request(@_resource_uri, 'GET', params, nil, false, is_voice_request: @_is_voice_request)
parse_and_set(response_json)
response_json
end
Expand Down
162 changes: 141 additions & 21 deletions lib/plivo/base_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module Plivo
class BaseClient
# Base stuff
attr_reader :headers, :auth_credentials

@@voice_retry_count = 0
def initialize(auth_id = nil, auth_token = nil, proxy_options = nil, timeout=5)
configure_credentials(auth_id, auth_token)
configure_proxies(proxy_options)
Expand All @@ -36,21 +36,42 @@ def process_response(method, response)
elsif !([200, 201, 202, 207].include? response[:status])
raise Exceptions::PlivoRESTError, "Received #{response[:status]} for #{method}"
end

@@voice_retry_count = 0
response[:body]
end

def send_request(resource_path, method = 'GET', data = {}, timeout = nil, use_multipart_conn = false)
def send_request(resource_path, method = 'GET', data = {}, timeout = nil, use_multipart_conn = false, options = nil)
timeout ||= @timeout

response = case method
when 'GET' then send_get(resource_path, data, timeout)
when 'POST' then send_post(resource_path, data, timeout, use_multipart_conn)
when 'DELETE' then send_delete(resource_path, data, timeout)
else raise_invalid_request("#{method} not supported by Plivo, yet")
end
if options[:is_voice_request] == true
response = case method
when 'GET' then send_get(resource_path, data, timeout, is_voice_request: options[:is_voice_request], voice_retry_count: @@voice_retry_count)
when 'POST' then send_post(resource_path, data, timeout, use_multipart_conn, is_voice_request: options[:is_voice_request], voice_retry_count: @@voice_retry_count)
when 'DELETE' then send_delete(resource_path, data, timeout, is_voice_request: options[:is_voice_request], voice_retry_count: @@voice_retry_count)
else raise_invalid_request("#{method} not supported by Plivo, yet")
end

if response.status >= 500
@@voice_retry_count += 1
if @@voice_retry_count > 2
return process_response(method, response.to_hash)
end
is_voice_request = true
send_request(resource_path, method, data, timeout, use_multipart_conn, is_voice_request: is_voice_request)
else
process_response(method, response.to_hash)
end

process_response(method, response.to_hash)
else
response = case method
when 'GET' then send_get(resource_path, data, timeout)
when 'POST' then send_post(resource_path, data, timeout, use_multipart_conn)
when 'DELETE' then send_delete(resource_path, data, timeout)
else raise_invalid_request("#{method} not supported by Plivo, yet")
end

process_response(method, response.to_hash)
end
end

private
Expand Down Expand Up @@ -118,6 +139,45 @@ def configure_connection
faraday.adapter Faraday.default_adapter
end

@voice_conn_no_retry = Faraday.new(@voice_base_uri) do |faraday|
faraday.headers = @headers

# DANGER: Basic auth should always come after headers, else
# The headers will replace the basic_auth

faraday.basic_auth(auth_id, auth_token)

faraday.proxy=@proxy_hash if @proxy_hash
faraday.response :json, content_type: /\bjson$/
faraday.adapter Faraday.default_adapter
end

@voice_conn_retry_1 = Faraday.new(@voice_base_uri_fallback_1) do |faraday|
faraday.headers = @headers

# DANGER: Basic auth should always come after headers, else
# The headers will replace the basic_auth

faraday.basic_auth(auth_id, auth_token)

faraday.proxy=@proxy_hash if @proxy_hash
faraday.response :json, content_type: /\bjson$/
faraday.adapter Faraday.default_adapter
end

@voice_conn_retry_2 = Faraday.new(@voice_base_uri_fallback_2) do |faraday|
faraday.headers = @headers

# DANGER: Basic auth should always come after headers, else
# The headers will replace the basic_auth

faraday.basic_auth(auth_id, auth_token)

faraday.proxy=@proxy_hash if @proxy_hash
faraday.response :json, content_type: /\bjson$/
faraday.adapter Faraday.default_adapter
end

@callinsights_conn = Faraday.new(@callinsights_base_uri) do |faraday|
faraday.headers = @headers

Expand All @@ -133,15 +193,34 @@ def configure_connection

end

def send_get(resource_path, data, timeout)
response = @conn.get do |req|
req.url resource_path, data
req.options.timeout = timeout if timeout
def send_get(resource_path, data, timeout, options = nil)
if options
if options[:voice_retry_count] == 0 and options[:is_voice_request] == true
response = @voice_conn_no_retry.get do |req|
req.url resource_path, data
req.options.timeout = timeout if timeout
end
elsif options[:voice_retry_count] == 1 and options[:is_voice_request] == true
response = @voice_conn_retry_1.get do |req|
req.url resource_path, data
req.options.timeout = timeout if timeout
end
elsif options[:voice_retry_count] == 2 and options[:is_voice_request] == true
response = @voice_conn_retry_2.get do |req|
req.url resource_path, data
req.options.timeout = timeout if timeout
end
end
else
response = @conn.get do |req|
req.url resource_path, data
req.options.timeout = timeout if timeout
end
end
response
end

def send_post(resource_path, data, timeout, use_multipart_conn)
def send_post(resource_path, data, timeout, use_multipart_conn, options = nil)
if use_multipart_conn
multipart_conn = Faraday.new(@base_uri) do |faraday|
faraday.headers = {
Expand Down Expand Up @@ -178,7 +257,26 @@ def send_post(resource_path, data, timeout, use_multipart_conn)
req.options.timeout = timeout if timeout
req.body = JSON.generate(data) if data
end

elsif options
if options[:voice_retry_count] == 0 and options[:is_voice_request] == true
response = @voice_conn_no_retry.post do |req|
req.url resource_path
req.options.timeout = timeout if timeout
req.body = JSON.generate(data) if data
end
elsif options[:voice_retry_count] == 1 and options[:is_voice_request] == true
response = @voice_conn_retry_1.post do |req|
req.url resource_path
req.options.timeout = timeout if timeout
req.body = JSON.generate(data) if data
end
elsif options[:voice_retry_count] == 2 and options[:is_voice_request] == true
response = @voice_conn_retry_2.post do |req|
req.url resource_path
req.options.timeout = timeout if timeout
req.body = JSON.generate(data) if data
end
end
else
response = @conn.post do |req|
req.url resource_path
Expand All @@ -190,11 +288,33 @@ def send_post(resource_path, data, timeout, use_multipart_conn)
response
end

def send_delete(resource_path, data, timeout)
response = @conn.delete do |req|
req.url resource_path
req.options.timeout = timeout if timeout
req.body = JSON.generate(data) if data
def send_delete(resource_path, data, timeout, options = nil)
if options
if options[:voice_retry_count] == 0 and options[:is_voice_request] == true
response = @voice_conn_no_retry.delete do |req|
req.url resource_path
req.options.timeout = timeout if timeout
req.body = JSON.generate(data) if data
end
elsif options[:voice_retry_count] == 1 and options[:is_voice_request] == true
response = @voice_conn_retry_1.delete do |req|
req.url resource_path
req.options.timeout = timeout if timeout
req.body = JSON.generate(data) if data
end
elsif options[:voice_retry_count] == 2 and options[:is_voice_request] == true
response = @voice_conn_retry_2.delete do |req|
req.url resource_path
req.options.timeout = timeout if timeout
req.body = JSON.generate(data) if data
end
end
else
response = @conn.delete do |req|
req.url resource_path
req.options.timeout = timeout if timeout
req.body = JSON.generate(data) if data
end
end
response
end
Expand Down
2 changes: 2 additions & 0 deletions lib/plivo/resources/applications.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def initialize(client, options = nil)
@_name = 'Application'
@_identifier_string = 'app_id'
super
@_is_voice_request = true
end

# @param [Hash] options
Expand Down Expand Up @@ -109,6 +110,7 @@ def initialize(client, resource_list_json = nil)
@_resource_type = Application
@_identifier_string = 'app_id'
super
@_is_voice_request = true
end

# @param [String] app_id
Expand Down
Loading

0 comments on commit 0a02957

Please sign in to comment.