Skip to content

refactor(backend): extract Gemini model fallback into reusable utility (DRY)#439

Merged
KaranUnique merged 1 commit into
Canopus-Labs:mainfrom
Jivan-Patel:main
Jul 13, 2026
Merged

refactor(backend): extract Gemini model fallback into reusable utility (DRY)#439
KaranUnique merged 1 commit into
Canopus-Labs:mainfrom
Jivan-Patel:main

Conversation

@Jivan-Patel

Copy link
Copy Markdown
Contributor

Summary

The Gemini model fallback loop was duplicated across 6 locations in 5 files.
This PR extracts it into a single reusable utility at utils/geminiHelper.js.

Changes

New: utils/geminiHelper.js

  • generateWithFallback(apiKey, parts, options?, retries?, initialDelay?) — tries
    candidate models in order (env var first), with optional exponential-backoff
    retries for transient errors (429, 503, timeout, network)
  • generateChatWithFallback(apiKey, prompt, history?, options?) — same fallback
    strategy for chat-session endpoints using startChat + sendMessage

Updated files

File Loops removed
controllers/aiController.js 3
controllers/resumeController.js 1
routes/aiRoutes.js 1 (chat)
routes/AptitudeQuestions.js 1 + local retry helpers

Benefits

  • ✅ Single source of truth for model list and fallback order
  • ✅ Retry logic (previously only in AptitudeQuestions) now available everywhere
  • ✅ ~90 lines of boilerplate removed
  • ✅ Fallback helper is independently unit-testable

Testing

All existing behaviour is preserved. No API surface changed.

Closes #435

Introduce utils/geminiHelper.js with two exported functions:

- generateWithFallback(apiKey, parts, options, retries, initialDelay)
  Tries candidate models in order (env GEMINI_MODEL first, then the
  hardcoded fallback list) and supports exponential-backoff retries for
  transient errors (429 / 503 / timeout / network).

- generateChatWithFallback(apiKey, prompt, history, options)
  Same model-fallback strategy but initialises a Gemini chat session
  (startChat + sendMessage) for the conversational AI endpoint.

The duplicated ~15-line fallback loops that appeared in 6 locations
across 5 files are removed and replaced with single calls to the helper:

  controllers/aiController.js     — 3 loops → 3 helper calls
  controllers/resumeController.js — 1 loop  → 1 helper call
  routes/aiRoutes.js              — 1 loop  → 1 helper call (chat)
  routes/AptitudeQuestions.js     — 1 loop  + local isRetryableError
                                    + generateWithRetry → 1 helper call

Benefits:
  * Single source of truth for model list and fallback order
  * Retry logic (previously only in AptitudeQuestions) is now available
    to all callers via the retries parameter
  * ~90 lines of boilerplate removed
  * Fallback helper is independently unit-testable

Closes #<issue-number>
@Jivan-Patel

Copy link
Copy Markdown
Contributor Author

Hello @KaranUnique, I have completed my assigned work so please review the changes and merge the PR under ECSoC.

@KaranUnique KaranUnique merged commit d2e222d into Canopus-Labs:main Jul 13, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(ai): centralize duplicated Gemini model fallback logic into a shared utility

2 participants