This repository is currently being migrated. It's locked while the migration is in progress.
-
Notifications
You must be signed in to change notification settings - Fork 94
Expand file tree
/
Copy pathmulti_provider_support.rb
More file actions
143 lines (118 loc) · 5.52 KB
/
multi_provider_support.rb
File metadata and controls
143 lines (118 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# frozen_string_literal: true
require 'benefits_claims/concerns/multi_provider_base'
# Web-specific implementation of multi-provider support for BenefitsClaimsController.
# Extends the shared BenefitsClaims::Concerns::MultiProviderBase with web-specific
# response formatting and metrics.
#
# Note: This concern references BenefitsClaimsController's STATSD_METRIC_PREFIX and
# STATSD_TAGS constants for metrics reporting. This coupling is intentional.
module V0
module Concerns
module MultiProviderSupport
extend ActiveSupport::Concern
include BenefitsClaims::Concerns::MultiProviderBase
LEGACY_PROVIDER_TYPE_ALIASES = {
'ivcchampvabenefitsclaimsprovider' => 'ivc_champva'
}.freeze
private
def format_error_entry(provider_name, message)
{ 'provider' => provider_name, 'error' => message }
end
def format_get_claims_response(claims_data, errors)
{ 'data' => claims_data, 'meta' => { 'provider_errors' => errors.presence }.compact }
end
def statsd_metric_name(action)
controller_class = self.class
"#{controller_class::STATSD_METRIC_PREFIX}.#{action}"
end
def statsd_tags_for_provider(provider_name)
controller_class = self.class
controller_class::STATSD_TAGS + ["provider:#{provider_name}"]
end
# Overrides base implementation to use explicit routing instead of fallback iteration.
#
# Retrieves a claim from the appropriate provider based on provider_type parameter.
#
# The type parameter is optional and defaults to lighthouse for backward compatibility
# with existing bookmarks/URLs. This means lighthouse claims can be accessed without
# specifying type, even when multiple providers exist. Other providers require the
# type parameter to be explicitly specified.
#
# For Lighthouse claims, routes through V0::LighthouseClaims::Proxy to apply
# web-specific transforms. Other providers use their provider implementation directly.
#
# Rollout strategy: Frontend will deploy first to send type parameter, then we enable
# the second provider. This ensures type is always present before it becomes required.
def get_claim_from_providers(claim_id, provider_type = nil)
# Default to lighthouse for backward compatibility when no type is specified.
# All paths go through get_claim_for_provider_type for consistent error handling.
get_claim_for_provider_type(claim_id, provider_type.presence || 'lighthouse')
end
# Routes claim request to appropriate implementation based on provider type.
# Lighthouse uses Proxy (with web-specific transforms), others use provider directly.
# Wraps provider calls with StatsD metrics and structured logging for ops visibility.
def get_claim_for_provider_type(claim_id, provider_type)
provider_class = provider_class_for_type(provider_type)
if lighthouse_provider?(provider_class)
lighthouse_proxy.get_claim(claim_id)
else
provider = provider_class.new(@current_user)
provider.get_claim(claim_id)
end
rescue Common::Exceptions::RecordNotFound
log_claim_not_found(provider_class)
raise
rescue Common::Exceptions::Unauthorized, Common::Exceptions::Forbidden,
Common::Exceptions::InvalidFieldValue
raise
rescue => e
handle_get_claim_error(provider_class, e)
raise
end
# Checks if a provider class is the Lighthouse provider
def lighthouse_provider?(provider_class)
provider_class.name.downcase.include?('lighthouse')
end
# Returns the web-specific Lighthouse Proxy
# This proxy includes web transforms (rename_rv1, suppress_evidence_requests)
def lighthouse_proxy
@lighthouse_proxy ||= V0::LighthouseClaims::Proxy.new(@current_user)
end
def provider_registry
@provider_registry ||= BenefitsClaims::Providers::ProviderRegistry.enabled_providers(@current_user)
end
def provider_class_for_type(type)
provider_type = normalized_provider_type(type)
provider = provider_registry.find { |p| p[:name].to_s == provider_type }
raise Common::Exceptions::InvalidFieldValue.new('type', type) if provider.nil?
provider[:class]
end
def supported_provider_types
provider_registry.map { |p| p[:name].to_s }
end
# Override base implementation to add provider field to each claim
# This enables the frontend to distinguish claims with identical IDs from different providers
def extract_claims_data(provider_class, response)
claims_data = super(provider_class, response)
provider_type = provider_type_from_class(provider_class)
# Add provider field to each claim
claims_data.each do |claim|
next unless claim.is_a?(Hash)
claim['attributes'] ||= {}
claim['attributes']['provider'] = provider_type
end
claims_data
end
# Maps provider class to provider type string via registry
def provider_type_from_class(provider_class)
provider = provider_registry.find { |p| p[:class] == provider_class }
raise Common::Exceptions::InvalidFieldValue.new('provider_class', provider_class.to_s) if provider.nil?
provider[:name].to_s
end
def normalized_provider_type(type)
normalized_type = type.to_s.downcase
LEGACY_PROVIDER_TYPE_ALIASES.fetch(normalized_type, normalized_type)
end
end
end
end