Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RT-749] raise timeout error for circuit breaker #17

Merged
merged 4 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion lib/factiva.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
Dir[File.join(__dir__, "factiva", "*.rb")].each { |file| require file }

module Factiva

REQUEST_API_ACCOUNT = "request_api_account"
MONITORING_API_ACCOUNT = "monitoring_api_account"

Expand Down
4 changes: 4 additions & 0 deletions lib/factiva/authentication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ def make_request(params)
end

response_body
rescue HTTP::TimeoutError
# This error should be handled before HTTP::Error which is a superclass of HTTP::TimeoutError
# Raising Factiva::TimeoutError is required for CircuitBreaker to work properly
raise Factiva::TimeoutError
end

def expired?(timestamp)
Expand Down
4 changes: 3 additions & 1 deletion lib/factiva/errors.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module Factiva
class RequestError < StandardError; end
class Error < StandardError; end
class RequestError < Error; end
class TimeoutError < Error; end
end
24 changes: 14 additions & 10 deletions lib/factiva/monitoring.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ module Factiva
class Monitoring
include Dry::Monads[:result]

private_class_method :new
attr_reader :auth

COUNTRY_IDS = {
"ES" => "SPAIN",
"FR" => "FRA",
"IT" => "ITALY",
"PT" => "PORL",
}.freeze

private_class_method :new
attr_reader :auth

def self.create_case(**args)
instance.create_case(**args)
end
Expand Down Expand Up @@ -74,9 +74,9 @@ def initialize(stubbed_create_case,
stubbed_get_matches,
stubbed_log_decision
)
@stubbed_create_case = stubbed_create_case
@stubbed_create_association = stubbed_create_association
@stubbed_add_association_to_case = stubbed_add_association_to_case
@stubbed_create_case = stubbed_create_case
@stubbed_create_association = stubbed_create_association
@stubbed_add_association_to_case = stubbed_add_association_to_case
@stubbed_get_matches = stubbed_get_matches
@stubbed_log_decision = stubbed_log_decision
end
Expand Down Expand Up @@ -117,7 +117,7 @@ def create_case(case_body_payload = nil)

def create_association(first_name:, last_name:, birth_year:, external_id:, nin:, country_code:)
params = { json: association_body(
first_name,
first_name,
last_name,
birth_year,
external_id,
Expand All @@ -134,7 +134,7 @@ def create_association(first_name:, last_name:, birth_year:, external_id:, nin:,

def add_association_to_case(case_id:, association_id:)
params = { json: case_association_body(
association_id,
association_id,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: This could be one line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there was 45 offenses, I let rubocop to fix them himself

)
}

Expand All @@ -153,7 +153,7 @@ def get_matches(case_id:)

def log_decision(case_id:, match_id:, comment:, state:, risk_rating:)
params = { json: log_decision_body(
comment, state, risk_rating,
comment, state, risk_rating,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: This could be one line

)
}

Expand Down Expand Up @@ -189,7 +189,7 @@ def make_request(http_method, url, params = nil)

begin
response = HTTP
.headers(:accept => "application/json")
.headers(accept: "application/json")
.headers("Content-Type" => "application/json")
.timeout(config.timeout)
.auth("Bearer #{auth.token}")
Expand All @@ -202,6 +202,10 @@ def make_request(http_method, url, params = nil)
else
Failure({ code: response.code, error: response_body["error"] }.to_s)
end
rescue HTTP::TimeoutError
# This error should be handled before HTTP::Error which is a superclass of HTTP::TimeoutError
# Raising Factiva::TimeoutError is required for CircuitBreaker to work properly
raise Factiva::TimeoutError
rescue SocketError, HTTP::Error => error
Failure("Failed to connect to Factiva: #{error.message}")
rescue JSON::ParserError => error
Expand Down
4 changes: 4 additions & 0 deletions lib/factiva/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ def make_request(method, url, params = nil)
else
Failure({ code: response.code, error: response_body["error"] }.to_s)
end
rescue HTTP::TimeoutError
# This error should be handled before HTTP::Error which is a superclass of HTTP::TimeoutError
# Raising Factiva::TimeoutError is required for CircuitBreaker to work properly
raise Factiva::TimeoutError
rescue SocketError, HTTP::Error => error
Failure("Failed to connect to Factiva: #{error.message}")
rescue JSON::ParserError => error
Expand Down
10 changes: 10 additions & 0 deletions spec/factiva/authentication_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ module Factiva
}.to raise_error(RequestError, { code: 400, error: "request_validation_error" }.to_s)
end
end

context "Factiva connection timed out" do
before do
WebMock.stub_request(:post, /oauth2\/v1\/token/).to_timeout
end

it "raises Factiva::TimeoutError for CircuitBreaker" do
expect { subject.token }.to raise_error(Factiva::TimeoutError)
end
end
end

context "Already authenticated" do
Expand Down
42 changes: 28 additions & 14 deletions spec/factiva/monitoring_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ module Factiva
}
}

context "when there isn't matches in the Case", vcr: "monitoring/no_matches" do # this VCR was recorded when there wasn't any match
# this VCR was recorded when there wasn't any match
context "when there isn't matches in the Case", vcr: "monitoring/no_matches" do
let(:case_id) { "91473caa-9eb8-4eb1-891d-bde3d7c80cdd" }

it "authenticates and doesn't get matches" do
Expand All @@ -96,7 +97,6 @@ module Factiva
end

context "when there are matches in the Case", vcr: "monitoring/matches" do

let(:case_id) { "296373b3-80ee-4fb7-9f2e-b43604051c0b" }

it "authenticates and returns 2 matches: 1 valid and 1 invalid" do
Expand All @@ -106,23 +106,23 @@ module Factiva
invalid_match = {
"peid" => "1003410",
"type" => "RELATIONSHIP",
"variation" => {"structural" => false, "linguistic" => false, "non_linguistic" => false},
"variation" => { "structural" => false, "linguistic" => false, "non_linguistic" => false },
"title" => "OFAC - Principal Significant Foreign Narcotics Trafficker List",
"match_id" => "239b4a188aff307a328984b0129dbb3a1fd5a9e9385e664fb3091fcce67ecd17",
"match_name" => "Maria Remedios Garcia Albert",
"match_type" => "PRECISE",
"percentage_match" =>1.0,
"percentage_match" => 1.0,
"subscription_name" => "Maria Remedios Garcia Albert",
"boosting_events" =>[],
"boosting_events" => [],
"icon_hints" => ["SAN-PERSON", "SI-PERSON"],
"primary_country" => "SPAIN",
"is_score_boosted" => false,
"current_state" => {"timestamp" => "2022-06-22T07:41:53", "state" => "OPEN"},
"birthdates" => [{"day" => 17, "year" => 1951, "month" => 2}],
"current_state" => { "timestamp" => "2022-06-22T07:41:53", "state" => "OPEN" },
"birthdates" => [{ "day" => 17, "year" => 1951, "month" => 2 }],
"gender" => "FEMALE",
"is_deceased" => false,
"match_date" => "2022-06-22T07:41:53",
"primary_name" => {"name_type" => "PRIMARY", "first_name" => "Maria Remedios", "last_name" => "Garcia Albert"},
"primary_name" => { "name_type" => "PRIMARY", "first_name" => "Maria Remedios", "last_name" => "Garcia Albert" },
"has_alerts" => false,
"is_match_valid" => false,
"match_invalid_date" => "2022-06-22T07:41:53.349",
Expand All @@ -132,7 +132,7 @@ module Factiva
valid_match = {
"peid" => "1003410",
"type" => "RELATIONSHIP",
"variation" => {"structural"=>false, "linguistic"=>false, "non_linguistic"=>false},
"variation" => { "structural" => false, "linguistic" => false, "non_linguistic" => false },
"title" => "OFAC - Principal Significant Foreign Narcotics Trafficker List",
"match_id" => "5e7a91388deea1e1368937aaa00c69635890f51e964909eb1f4daccf2ee69ca5",
"match_name" => "Maria Remedios Garcia Albert",
Expand All @@ -143,20 +143,21 @@ module Factiva
"icon_hints" => ["SAN-PERSON", "SI-PERSON"],
"primary_country" => "SPAIN",
"is_score_boosted" => false,
"current_state" => {"timestamp" => "2022-06-22T07:41:54", "state" => "OPEN"},
"birthdates" => [{"day"=>17, "year"=>1951, "month"=>2}],
"current_state" => { "timestamp" => "2022-06-22T07:41:54", "state" => "OPEN" },
"birthdates" => [{ "day" => 17, "year" => 1951, "month" => 2 }],
"gender" => "FEMALE",
"is_deceased" => false,
"match_date" => "2022-06-22T07:41:54",
"primary_name" => {"name_type" => "PRIMARY", "first_name" => "Maria Remedios", "last_name" => "Garcia Albert"},
"primary_name" => { "name_type" => "PRIMARY", "first_name" => "Maria Remedios", "last_name" => "Garcia Albert" },
"has_alerts" => true,
"is_match_valid" => true,
}.freeze

expect(result["data"][0]["attributes"]["external_id"]).to eq("id-XXXXXXX")
expect(result["data"][0]["attributes"]["matches"][0]["subscription_name"]).to eq("Maria Remedios Garcia Albert")
expect(result["data"][0]["attributes"]["matches"][0]["is_match_valid"]).to be_falsey
expect(result["data"][0]["attributes"]["matches"][0]["match_invalid_reason"]).to eq "Match excluded by filter: year_of_birth"
expect(result["data"][0]["attributes"]["matches"][0]["match_invalid_reason"])
.to eq "Match excluded by filter: year_of_birth"
expect(result["data"][0]["attributes"]["matches"][0]).to eq(invalid_match)

expect(result["data"][1]["attributes"]["external_id"]).to eq("id1234")
Expand All @@ -165,6 +166,18 @@ module Factiva
expect(result["data"][1]["attributes"]["matches"][0]).to eq(valid_match)
end
end

context "Factiva connection timed out", vcr: "monitoring/authentication_only" do
before do
WebMock.stub_request(:get, /risk-entity-screening-cases/).to_timeout
end

it "raises Factiva::TimeoutError for CircuitBreaker" do
expect {
subject.get_matches(case_id: "id")
}.to raise_error(Factiva::TimeoutError)
end
end
end

describe "#log_decision", vcr: "monitoring/log_decision" do
Expand All @@ -181,7 +194,8 @@ module Factiva
it "authenticates and Logs a decision to a Match" do
res = subject.log_decision(**sample_data)

expect(res["data"]["attributes"]["current_state"]).to eq({"timestamp"=>"2022-06-21T10:04:37.645", "comment"=>"False positive", "state"=>"CLEARED", "risk_rating"=>1})
expect(res["data"]["attributes"]["current_state"]).to eq({ "timestamp" => "2022-06-21T10:04:37.645",
"comment" => "False positive", "state" => "CLEARED", "risk_rating" => 1 })
end
end
end
Expand Down
24 changes: 24 additions & 0 deletions spec/factiva/request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,18 @@ module Factiva
}.to raise_error(RequestError, "Failed to connect to Factiva: SocketError")
end
end

context "Factiva connection timed out", vcr: "search/authentication_only" do
before do
WebMock.stub_request(:post, /riskentities\/search/).to_timeout
end

it "raises Factiva::TimeoutError for CircuitBreaker" do
expect {
subject.search(**params)
}.to raise_error(Factiva::TimeoutError)
end
end
end

context "#Profile" do
Expand Down Expand Up @@ -166,6 +178,18 @@ module Factiva
}.to raise_error(RequestError, "Failed to connect to Factiva: SocketError")
end
end

context "Factiva connection timed out", vcr: "profile/authentication_only" do
before do
WebMock.stub_request(:get, /riskentities\/profiles/).to_timeout
end

it "raises Factiva::TimeoutError for CircuitBreaker" do
expect {
subject.profile(profile_id)
}.to raise_error(Factiva::TimeoutError)
end
end
end

context "#Stub!" do
Expand Down
4 changes: 4 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@
config.expect_with :rspec do |c|
c.syntax = :expect
end

config.after(:each) do
WebMock.reset!
end
end
3 changes: 2 additions & 1 deletion spec/support/vcr_setup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
c.filter_sensitive_data("<SECRET_USERNAME>") { URI.encode_www_form_component(Factiva.configuration.username) }
c.filter_sensitive_data("<SECRET_CLIENT_ID>") { Factiva.configuration(Factiva::MONITORING_API_ACCOUNT).client_id }
c.filter_sensitive_data("<SECRET_PASSWORD>") { Factiva.configuration(Factiva::MONITORING_API_ACCOUNT).password }
c.filter_sensitive_data("<SECRET_USERNAME>") { URI.encode_www_form_component(Factiva.configuration(Factiva::MONITORING_API_ACCOUNT).username) }
c.filter_sensitive_data("<SECRET_USERNAME>") {
URI.encode_www_form_component(Factiva.configuration(Factiva::MONITORING_API_ACCOUNT).username) }
end
Loading
Loading