Add stale fallback for domain listing on business registry outage - #2916
Open
OlegPhenomenon wants to merge 9 commits into
Open
OlegPhenomenon wants to merge 9 commits into
OlegPhenomenon wants to merge 9 commits into
Conversation
…ilable Domain listing endpoint no longer returns empty results when the business registry SOAP service is down. A new ListingCompanyCodesResolver service provides cache-first lookup with bounded stale fallback for company codes, used exclusively in the read-only domains#index path. Direct domains are always preserved; company-linked domains degrade gracefully. Write paths (registry locks, contacts) remain unchanged. Resolves registrant_center#165
CompanyRegister::Client already caches representation_rights responses internally via cache_store.fetch with cache_period TTL. The resolver was duplicating this with its own primary key. Now the resolver only maintains a stale fallback key — the gem handles primary caching.
Adds registrant user, contacts, and domains for testing the company codes stale fallback feature via TARA test login (60001019906). Pre-populates both gem cache and stale cache so company-linked domains are visible immediately. Includes instructions for simulating outage.
After switching the company_register gem from HTTPI to Net::HTTP adapter, network-level errors like Net::OpenTimeout bubble up from the SOAP client without being wrapped into CompanyRegister::NotAvailableError. This caused domains#index to return 500 instead of falling back to direct domains when the business registry was unreachable. Resolver now catches Net::OpenTimeout, Net::ReadTimeout, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ETIMEDOUT, SocketError and OpenSSL::SSL::SSLError and treats them the same as NotAvailableError: fall back to stale cache, log as 'network_error'.
On staging the company_register gem uses the HTTPI adapter, which raises HTTPI::SSLError / HTTPI::Error for network problems. These were bubbling up past the resolver's rescue and causing 500 responses. Resolver now catches HTTPI::Error (when HTTPI is loaded) alongside the Net::HTTP-era error classes. Added a regression test that raises HTTPI::SSLError and expects stale fallback.
The resolver guarded the listing against raw transport errors, but every other caller of the business registry still crashed on them: domains#show, the registrant contacts endpoints and the companies endpoint rescue CompanyRegister::NotAvailableError only, which no real outage ever raises. There was also no timeout at all, so a hanging registry held a request thread until the HTTP adapter gave up at 60s - long past the portal's own 15s budget. - Point company_register at fix/165-transport-errors-not-available, where transport failures are normalised into NotAvailableError and open/read timeouts (5s/10s) are applied. Back to master once that branch is merged. - Correct the NETWORK_ERRORS comment: with the gem normalising, this list is a second line of defence against a future adapter or failure class, not the only thing standing between an outage and a 500. - Cover domains#show during an outage; it goes through the controller rescue rather than the resolver and had no test.
Resolves the .gitignore conflict: both sides append to the same tail. Keeps master's repowise entries and drops the AGENT.md/own duplicates the two histories produced (AGENT.md is already listed above, and `own/` covers the same path as `own`).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ListingCompanyCodesResolverservice: cache-first company codes lookup with bounded stale fallback for the read-only domain listing pathDomain.listing_user_domains,Contact.org_contacts_by_codes) that accept pre-resolved company codes without callingRegistrantUser#companiesdomains#indexnow uses the resolver once per request; direct domains are always preserved, company-linked domains degrade gracefullyregistry_locks, contacts, EPP) remain completely unchanged — no stale fallback for mutationsWhat changes
app/services/listing_company_codes_resolver.rbapp/models/domain.rblisting_user_domains/listing_user_domains_countscopesapp/models/contact.rborg_contacts_by_codesclass methodapp/controllers/api/v1/registrant/domains_controller.rbindexuses resolver;showunchangedTest plan
test/services/listing_company_codes_resolver_test.rb— 17 tests (cache hit, live success, stale fallback, SOAP fault, cache write failure, ident dash early return, logging)test/models/contact_test.rb— org_contacts_by_codes teststest/models/domain_test.rb— listing scope tests (direct, company-linked, dedupe, admin flag)test/integration/api/v1/registrant/domains_test.rb— 8 integration tests (live success, outage+stale, outage+no cache, SOAP fault, totals, resolver once per request, JSON shape)test/integration/api/v1/registrant/registry_locks_test.rb— negative regression (resolver not used, write path unchanged)Close internetee/registrant_center#165