Skip to content

Commit 8b696f4

Browse files
committed
Merge branch 'release/3.0.2'
* release/3.0.2: 3.0.2 Removed Faraday dependency, fixes issue with infinite retries, upgrade to use 2.7.4.
2 parents f65a1cb + b02208f commit 8b696f4

11 files changed

Lines changed: 92 additions & 52 deletions

File tree

.ruby-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.6.5
1+
2.7.4

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ sudo: false
33
language: ruby
44
cache: bundler
55
rvm:
6-
- 2.6.3
7-
before_install: gem install bundler -v 1.17.3
6+
- 2.7.4
7+
before_install: gem install bundler -v 2.2.15

Gemfile.lock

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
emailable (3.0.0)
5-
faraday
6-
faraday_middleware
7-
net-http-persistent
4+
emailable (3.0.2)
85

96
GEM
107
remote: https://rubygems.org/
@@ -22,14 +19,6 @@ GEM
2219
builder (3.2.3)
2320
coderay (1.1.2)
2421
concurrent-ruby (1.1.7)
25-
connection_pool (2.2.3)
26-
faraday (1.3.0)
27-
faraday-net_http (~> 1.0)
28-
multipart-post (>= 1.2, < 3)
29-
ruby2_keywords
30-
faraday-net_http (1.0.1)
31-
faraday_middleware (1.0.0)
32-
faraday (~> 1.0)
3322
i18n (1.8.5)
3423
concurrent-ruby (~> 1.0)
3524
method_source (0.9.2)
@@ -39,15 +28,11 @@ GEM
3928
builder
4029
minitest (>= 5.0)
4130
ruby-progressbar
42-
multipart-post (2.1.1)
43-
net-http-persistent (4.0.1)
44-
connection_pool (~> 2.2)
4531
pry (0.12.2)
4632
coderay (~> 1.1.0)
4733
method_source (~> 0.9.0)
4834
rake (13.0.1)
4935
ruby-progressbar (1.10.1)
50-
ruby2_keywords (0.0.4)
5136
thread_safe (0.3.6)
5237
tzinfo (1.2.8)
5338
thread_safe (~> 0.1)
@@ -67,4 +52,4 @@ DEPENDENCIES
6752
rake (~> 13.0)
6853

6954
BUNDLED WITH
70-
1.17.3
55+
2.1.4

LICENSE.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2019 Emailable. https://emailable.com
3+
Copyright (c) 2021 Emailable. https://emailable.com
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

emailable.gemspec

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ Gem::Specification.new do |s|
2727
end
2828
s.require_paths = ['lib']
2929

30-
s.add_dependency 'faraday'
31-
s.add_dependency 'faraday_middleware'
32-
s.add_dependency 'net-http-persistent'
3330
s.add_development_dependency 'bundler'
3431
s.add_development_dependency 'rake', '~> 13.0'
3532
s.add_development_dependency 'pry'

lib/emailable.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
require 'faraday'
2-
require 'faraday_middleware'
31
require 'emailable/version'
42
require 'emailable/client'
3+
require 'emailable/response'
54
require 'emailable/batch'
65
require 'emailable/resources/api_resource'
76
require 'emailable/resources/account'
@@ -14,9 +13,13 @@
1413

1514
module Emailable
1615
@max_network_retries = 1
16+
@open_timeout = 30
17+
@read_timeout = 60
18+
@write_timeout = 30
1719

1820
class << self
19-
attr_accessor :api_key, :max_network_retries
21+
attr_accessor :api_key, :max_network_retries, :open_timeout, :read_timeout,
22+
:write_timeout
2023
end
2124

2225
module_function

lib/emailable/batch.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@ class Batch
44

55
def initialize(id_or_emails, callback: nil)
66
if id_or_emails.is_a?(Array)
7+
@id = nil
78
@emails = id_or_emails
89
@callback = callback
910
elsif id_or_emails.is_a?(String)
1011
@id = id_or_emails
12+
@emails = nil
13+
@callback = nil
1114
else
1215
raise ArgumentError, 'expected an array of emails or batch id'
1316
end
1417

1518
@client = Emailable::Client.new
19+
@status = nil
1620
end
1721

1822
def verify

lib/emailable/client.rb

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,30 @@ module Emailable
22
class Client
33

44
def initialize
5-
@client = Faraday.new('https://api.emailable.com/v1') do |f|
6-
f.request :url_encoded
7-
f.response :json, content_type: /\bjson$/
8-
f.adapter :net_http_persistent
9-
end
5+
@base_url = 'https://api.emailable.com/v1'
6+
@connection = create_connection(URI(@base_url))
107
end
118

12-
def request(method, endpoint, opts = {})
9+
def request(method, endpoint, params = {})
1310
begin
14-
tries ||= 0
11+
tries ||= 3
1512

16-
@client.params[:api_key] = Emailable.api_key
13+
uri = URI("#{@base_url}/#{endpoint}")
14+
params[:api_key] = Emailable.api_key
1715

18-
response =
16+
http_response =
1917
if method == :get
20-
@client.get(endpoint, opts)
18+
uri.query = URI.encode_www_form(params)
19+
@connection.get(uri)
2120
elsif method == :post
22-
@client.post(endpoint, opts)
21+
request = Net::HTTP::Post.new(uri, 'Content-Type': 'application/json')
22+
request.body = params.to_json
23+
@connection.request(request)
2324
end
25+
26+
response = Response.new(http_response)
2427
rescue => e
25-
retry if self.class.should_retry?(e, tries)
28+
retry if (tries -= 1) > 0 && self.class.should_retry?(e, tries)
2629

2730
raise e
2831
end
@@ -48,23 +51,59 @@ def request(method, endpoint, opts = {})
4851
raise error_map[status.to_s].new(error_attributes)
4952
end
5053

54+
private
55+
56+
def create_connection(uri)
57+
connection = Net::HTTP.new(uri.host, uri.port)
58+
59+
# Time in seconds within which Net::HTTP will try to reuse an already
60+
# open connection when issuing a new operation. Outside this window, Ruby
61+
# will transparently close and re-open the connection without trying to
62+
# reuse it.
63+
#
64+
# Ruby's default of 2 seconds is almost certainly too short. Here I've
65+
# reused Go's default for `DefaultTransport`.
66+
connection.keep_alive_timeout = 30
67+
68+
connection.open_timeout = Emailable.open_timeout
69+
connection.read_timeout = Emailable.read_timeout
70+
if connection.respond_to?(:write_timeout=)
71+
connection.write_timeout = Emailable.write_timeout
72+
end
73+
connection.use_ssl = uri.scheme == "https"
74+
75+
connection
76+
end
77+
5178
def self.should_retry?(error, num_retries)
5279
return false if num_retries >= Emailable.max_network_retries
5380

54-
# Retry on timeout-related problems (either on open or read).
55-
return true if error.is_a?(Faraday::TimeoutError)
81+
case error
82+
when Net::OpenTimeout, Net::ReadTimeout
83+
# Retry on timeout-related problems (either on open or read).
84+
true
85+
when EOFError, Errno::ECONNREFUSED, Errno::ECONNRESET,
86+
Errno::EHOSTUNREACH, Errno::ETIMEDOUT, SocketError
87+
# Destination refused the connection, the connection was reset, or a
88+
# variety of other connection failures. This could occur from a single
89+
# saturated server, so retry in case it's intermittent.
90+
true
91+
when Net::HTTPError
92+
# 409 Conflict
93+
return true if error.http_status == 409
5694

57-
# Destination refused the connection, the connection was reset, or a
58-
# variety of other connection failures. This could occur from a single
59-
# saturated server, so retry in case it's intermittent.
60-
return true if error.is_a?(Faraday::ConnectionFailed)
95+
# 429 Too Many Requests
96+
return true if error.http_status == 429
6197

62-
if error.is_a?(Faraday::ClientError) && error.response
63-
# 409 conflict
64-
return true if error.response[:status] == 409
65-
end
98+
# 500 Internal Server Error
99+
return true if error.http_status == 500
66100

67-
false
101+
# 503 Service Unavailable
102+
error.http_status == 503
103+
else
104+
false
105+
end
68106
end
107+
69108
end
70109
end

lib/emailable/email_validator.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def validate_each(record, attribute, value)
3838

3939
api_options = { timeout: timeout, smtp: smtp }
4040
api_options[:accept_all] = true unless accept_all
41-
ev = Emailable.verify(value, api_options)
41+
ev = Emailable.verify(value, **api_options)
4242

4343
result_accessor = "#{attribute}_verification_result"
4444
if record.respond_to?(result_accessor)

lib/emailable/response.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module Emailable
2+
class Response
3+
4+
attr_accessor :status, :body
5+
6+
def initialize(response)
7+
@status = response.code.to_i
8+
@body = JSON.parse(response.body)
9+
end
10+
11+
end
12+
end

0 commit comments

Comments
 (0)