Skip to content

Retry logic and failure handling are inconsistent across near-identical services #52

Description

@2ndtlmining

Labels: bug, reliability, tech-debt

Problem

Five services all fetch from the same class of Flux stats API and count/sum results, but handle failure completely differently:

Service Retry on failure Falls back to last-good data Logging style
cloudService.js 2x, shared retryApiCall() helper Returns cached data structured (createLogger)
gamingService.js 3x / 10s delay, inline loop Throws, no fallback console.log/console.error
cryptoService.js 3x / 10s delay, inline loop (near-duplicate of gaming's) Throws, no fallback console.log/console.error
wordpressService.js None Throws, no fallback console.log/console.error
nodeService.js None Throws, no fallback console.log/console.error

cloudService.js is the most resilient — it retries, and on total failure returns last-known-good cached data instead of leaving the dashboard blank or throwing. The other four either throw immediately or throw after retries with no fallback, so a single bad response from Flux's API can leave that metric stuck or erroring with no graceful degradation.

gamingService.js and cryptoService.js also contain near-identical fetch/count/retry code (same structure, different config object) — a maintenance risk, since a fix applied to one is easy to forget on the other. This kind of duplication is part of how the original stale-count issue could get worse over time.

Solution

  1. Extract cloudService.js's retryApiCall() + cache-fallback pattern into a shared helper, e.g. src/lib/services/resilientFetch.js:
   export async function resilientFetch(url, { retries = 2, timeout = 15000, cacheKey } = {}) {
       // retry loop + cache fallback, generalized from cloudService.js
   }
  1. Have gamingService.js, cryptoService.js, wordpressService.js, and nodeService.js all use it instead of their own copy-pasted or missing retry logic.
  2. Collapse gamingService.js and cryptoService.js into one generic function:
   export async function fetchRepoStats(REPOS_CONFIG, totalDbKey, syncStatusName) {
       // shared node/app/image counting loop, parameterized by config
   }

and have both gaming and crypto call it with their respective config.
4. Standardize all five services on the existing createLogger() pattern (already used in cloudService.js, revenueScheduler.js, servicesScheduler.js, database.js) instead of raw console.log, for consistent, filterable logs.

Files: src/lib/services/gamingService.js, cryptoService.js, wordpressService.js, nodeService.js, cloudService.js (source of the pattern to extract)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions