Skip to content

Commit 69f4df3

Browse files
committed
failover to other random endpoint when one is unreachable. Initialize with randomly choosen endpoint to somewhat fairly distribute load
1 parent 3e9a560 commit 69f4df3

File tree

5 files changed

+31
-7
lines changed

5 files changed

+31
-7
lines changed

Rakefile

+2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ require 'rake/clean'
44

55
Rake::TestTask.new("spec:unit") do |spec|
66
spec.libs.push "lib"
7+
spec.libs.push "spec"
78
spec.libs.push "spec/unit"
89
spec.test_files = FileList['spec/unit/**/*_spec.rb']
910
spec.warning = true
1011
end
1112

1213
Rake::TestTask.new("spec:integration") do |spec|
1314
spec.libs.push "lib"
15+
spec.libs.push "spec"
1416
spec.test_files = FileList['spec/integration/**/*_spec.rb']
1517
spec.warning = true
1618
end

lib/intercom.rb

+18-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module Intercom
2323
@hostname = "api.intercom.io"
2424
@protocol = "https"
2525
@endpoints = nil
26+
@current_endpoint = nil
2627
@app_id = nil
2728
@api_key = nil
2829

@@ -48,19 +49,32 @@ def self.api_key=(api_key)
4849
def self.target_base_url
4950
raise ArgumentError, "You must set both Intercom.app_id and Intercom.api_key to use this client. See https://github.com/intercom/intercom-ruby for usage examples." if [@app_id, @api_key].any?(&:nil?)
5051
basic_auth_part = "#{@app_id}:#{@api_key}@"
51-
endpoints[0].gsub(/(https?:\/\/)(.*)/, "\\1#{basic_auth_part}\\2")
52+
current_endpoint.gsub(/(https?:\/\/)(.*)/, "\\1#{basic_auth_part}\\2")
5253
end
5354

5455
def self.send_request_to_path(request)
5556
request.execute(target_base_url)
5657
rescue Intercom::ServiceReachableError => e
57-
if @endpoints && @endpoints.length > 1
58+
if endpoints.length > 1
59+
endpoint_unreachable
5860
request.execute(target_base_url)
5961
else
6062
raise e
6163
end
6264
end
6365

66+
def self.current_endpoint
67+
@current_endpoint ||= random_endpoint
68+
end
69+
70+
def self.random_endpoint
71+
(endpoints.shuffle - [@current_endpoint]).first
72+
end
73+
74+
def self.endpoint_unreachable
75+
@current_endpoint = random_endpoint
76+
end
77+
6478
def self.post(path, payload_hash)
6579
send_request_to_path(Intercom::Request.post(path, payload_hash))
6680
end
@@ -101,10 +115,12 @@ def self.hostname=(override) #nodoc
101115

102116
def self.endpoint=(endpoint) #nodoc
103117
self.endpoints = [endpoint]
118+
@current_endpoint = nil
104119
end
105120

106121
def self.endpoints=(endpoints) #nodoc
107122
@endpoints = endpoints
123+
@current_endpoint = nil
108124
end
109125

110126
def self.endpoints

spec/integration/intercom_api_integration_spec.rb

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
require 'intercom'
2-
require 'minitest/autorun'
1+
require "spec_helper"
32

43
describe "api.intercom.io dummy data requests" do
54
before :each do
@@ -56,7 +55,7 @@
5655
end
5756

5857
it "should failover to good endpoint when first one is un-reachable" do
59-
Intercom.endpoints = ["http://127.0.0.7", "https://api.intercom.io"]
58+
Intercom.endpoints = unshuffleable_array(["http://127.0.0.7", "https://api.intercom.io"])
6059
user = Intercom::User.find(:email => "[email protected]")
6160
user.name.must_equal "Somebody"
6261
end

spec/unit/spec_helper.rb spec/spec_helper.rb

+7
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,11 @@ def capture_exception(&block)
9797
rescue => e
9898
return e
9999
end
100+
end
101+
102+
def unshuffleable_array(array)
103+
def array.shuffle
104+
self
105+
end
106+
array
100107
end

spec/unit/intercom_spec.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@
2929
before do
3030
@protocol = Intercom.protocol
3131
@hostname = Intercom.hostname
32+
Intercom.endpoints = nil
3233
end
3334

3435
after do
3536
Intercom.protocol = @protocol
3637
Intercom.hostname = @hostname
37-
Intercom.endpoints = nil
3838
end
3939

4040
it "allows overriding of the endpoint and protocol" do
@@ -46,7 +46,7 @@
4646
it "prefers endpoints" do
4747
Intercom.endpoint = "https://localhost:7654"
4848
Intercom.target_base_url.must_equal "https://abc123:super-secret-key@localhost:7654"
49-
Intercom.endpoints = ["http://example.com","https://localhost:7654"]
49+
Intercom.endpoints = unshuffleable_array(["http://example.com","https://localhost:7654"])
5050
Intercom.target_base_url.must_equal "http://abc123:[email protected]"
5151
end
5252

0 commit comments

Comments
 (0)