Module: StandardSingpass::Myinfo::FailureClassifier
- Extended by:
- T::Sig
- Defined in:
- lib/standard_singpass/myinfo/failure_classifier.rb
Overview
Decides whether a Myinfo failure is Singpass's side being unavailable or our request being wrong.
The distinction exists because it changes what the host tells the user. An unavailable upstream clears itself within minutes, so the honest instruction is "try again shortly"; telling someone "something on our side stopped the verification — contact support and quote this reference" is both wrong and a dead end. Conversely, presenting a genuine integration bug as a transient blip sends the user round a loop that will never succeed.
This lives in the gem rather than in each host because the rule is entirely Myinfo protocol knowledge: which statuses Singpass uses for upstream-agency outages, and which of the gem's own exception classes represent an unreachable endpoint. Hosts typically need the same answer at more than one call site (a callback's result branch and a controller's rescue), so it is a module function rather than a private method on either.
Constant Summary collapse
- UPSTREAM_UNAVAILABLE_STATUSES =
502 is Singpass's documented signal that a Myinfo upstream agency (CPF Board, IRAS, MOM, …) is unavailable — returned both for genuine blips and throughout their published maintenance windows. 503/504 are the generic unavailable/gateway-timeout equivalents. https://docs.developer.singpass.gov.sg/docs/products/singpass-myinfo/scheduled-downtimes
Client::RETRYABLE_USERINFO_STATUSESis an alias of this list: the statuses worth one more automatic attempt are exactly the statuses that mean "their side, transient". T.let([502, 503, 504].freeze, T::Array[Integer])
Class Method Summary collapse
Class Method Details
.upstream_unavailable?(error) ⇒ Boolean
48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/standard_singpass/myinfo/failure_classifier.rb', line 48 def self.upstream_unavailable?(error) # Rate limiting counts: temporary, clears on its own, and the advice # the host gives the user is identical. return true if error.is_a?(RateLimitError) return false unless error.is_a?(Error) # A transport failure never reached Singpass at all, which is still # their endpoint being unreachable from here. return true if error.transport? # `status` is nil for an error a host raised itself; that falls # through to false rather than being guessed at. UPSTREAM_UNAVAILABLE_STATUSES.include?(error.status) end |