Skip to content

Fix media database API degradation#153

Merged
wizzomafizzo merged 5 commits into
mainfrom
fix/issue-143-media-db-degradation
Jun 3, 2026
Merged

Fix media database API degradation#153
wizzomafizzo merged 5 commits into
mainfrom
fix/issue-143-media-db-degradation

Conversation

@wizzomafizzo

@wizzomafizzo wizzomafizzo commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • downgrade expected unsupported/setup media database API failures to warnings
  • gate media database update controls on supported Core versions
  • degrade initial media fetch failures to safe missing-database UI states
  • add coverage for CoreAPI logging, media card, connection, and search handling

Closes #143

Validated with targeted tests, format check, typecheck, and lint.

Summary by CodeRabbit

  • New Features

    • Media database updates gated to Core 2.7.0+ with new UI states for unsupported cores and missing setup
    • Default games-index fallback when media DB is unavailable
  • Bug Fixes

    • Expected media/database-setup errors no longer trigger noisy failure toasts or logs
    • Action controls disabled when generation is unsupported or unavailable
  • UI Updates

    • Inline generate-error messages and new status texts; translations added
  • Tests

    • Expanded coverage for media error classification, update workflows, and logging behavior

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@wizzomafizzo, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 1 minute and 49 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6c6b9cd6-d2a1-4218-bfef-11e9298f4bb1

📥 Commits

Reviewing files that changed from the base of the PR and between 0ecd09c and e644a3b.

📒 Files selected for processing (1)
  • src/translations/en-US.json
📝 Walkthrough

Walkthrough

Centralize media-related CoreAPI error classification/logging, add a mediaGenerate feature gate and DEFAULT_GAMES_INDEX, and update ConnectionProvider, Search, MediaDatabaseCard, translations, and tests to gracefully handle unsupported Core or missing media-database setup.

Changes

Media database error handling and feature gating

Layer / File(s) Summary
Core API error classification and logging
src/lib/coreApi.ts
Add getErrorMessage and exported predicates isUnsupportedMediaApiError, isMissingMediaDatabaseSetupError, isExpectedMediaDatabaseError; introduce logMediaApiFailure and replace direct logger.error calls in media-related catch blocks.
Media generation feature gate
src/lib/featureGates.ts
Add mediaGenerate feature gate (since "2.7.0") used to determine availability of media-generation UI/actions.
DEFAULT games index export
src/lib/store.ts
Export DEFAULT_GAMES_INDEX as the canonical empty/default IndexResponse for gamesIndex resets.
ConnectionProvider media fetch error handling
src/components/ConnectionProvider.tsx
On expected media-database errors from CoreAPI.media(), set gamesIndex to DEFAULT_GAMES_INDEX and return early to avoid generic logging/toasts.
Search component media fetch error handling
src/routes/-pages/Search.tsx
Detect expected media-database errors and reset gamesIndex to DEFAULT_GAMES_INDEX, exiting the error handler early.
MediaDatabaseCard feature availability and error states
src/components/MediaDatabaseCard.tsx
Gate update actions on coreVersion via feature gate, add generateError state, convert update/cancel/resume flows to distinguish missing-setup/expected/other errors, add unsupported/setup-missing UI branches, and disable controls when unavailable.
UI translations for media generation
src/translations/en-US.json
Add updateDb.status.unsupported, updateDb.status.setupMissing, updateDb.startError, and features.mediaGenerate.
Core API contract tests
src/__tests__/unit/coreApi.api-contract.test.ts
Add simulateError helper, restore mocks in afterEach, and add negative-path tests asserting logging/no-logging behavior for unsupported/missing-setup vs unexpected media API errors.
Lib unit tests (coreApi)
src/__tests__/unit/lib/coreApi.test.ts
Add tests for isUnsupportedMediaApiError, isMissingMediaDatabaseSetupError, and isExpectedMediaDatabaseError.
Component and route tests
src/__tests__/unit/components/ConnectionProvider.test.tsx, src/__tests__/unit/components/MediaDatabaseCard.test.tsx, src/__tests__/unit/routes/create.search.test.tsx
Extend mocks with isExpectedMediaDatabaseError, add tests for unsupported Core gating, missing DBConfig handling (gamesIndex reset and setupMissing UI), generate-error clearing on cancel/resume, and suppression of toast for expected errors.
Import specifier cleanup
multiple src/routes/*, src/components/ZapScriptInput.tsx
Remove explicit .ts file extensions from @/lib/coreApi imports for consistency.

Sequence Diagram(s)

(suppressed — changes are primarily error classification, UI gating, and tests; no new multi-component sequential workflow requiring visualization)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hop where DBConfig cannot be found,
I hush the toasts and keep the logs sound.
Gates check the version, defaults take hold,
Warnings whisper softly — the rabbit is bold.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix media database API degradation' clearly and concisely summarizes the main change in the changeset, which involves handling media database API failures gracefully.
Linked Issues check ✅ Passed All coding objectives from issue #143 are met: core feature gates for media generation added (featureGates.ts), error classification helpers created and integrated throughout coreApi.ts, ConnectionProvider and MediaDatabaseCard handle expected failures with safe UI degradation, and comprehensive test coverage validates these paths.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #143: error handling/classification, feature gating, logging improvements, and supporting test coverage. Import statement cleanups removing .ts extensions are minimal incidental changes supporting the core work.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-143-media-db-degradation

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Jun 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.49558% with 13 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/components/MediaDatabaseCard.tsx 83.82% 9 Missing and 2 partials ⚠️
src/lib/coreApi.ts 94.73% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (4)
src/routes/-pages/Search.tsx (1)

13-13: ⚡ Quick win

Make the coreApi import consistent (optional)

Search.tsx imports @/lib/coreApi.ts, but this repo already imports @/lib/coreApi.ts in other places and tsconfig.json sets "allowImportingTsExtensions": true, so the extension itself isn’t inherently invalid. For consistency with src/components/ConnectionProvider.tsx, you can drop the .ts extension.

🔧 Proposed fix
-import { CoreAPI, isExpectedMediaDatabaseError } from "`@/lib/coreApi.ts`";
+import { CoreAPI, isExpectedMediaDatabaseError } from "`@/lib/coreApi`";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/-pages/Search.tsx` at line 13, The import in Search.tsx uses the
.ts extension which is inconsistent with other imports (e.g.,
ConnectionProvider.tsx); update the import statement that currently reads
"`@/lib/coreApi.ts`" to "`@/lib/coreApi`" so it matches the repo style and tsconfig
setting, and run a quick search for any other imports with the .ts extension of
coreApi to normalize them as well.
src/components/ConnectionProvider.tsx (1)

597-608: ⚡ Quick win

Confirm reset semantics for totalMedia, and dedupe the reset literal

  • IndexResponse.totalMedia is optional, and setGamesIndex replaces the entire gamesIndex object (set({ gamesIndex: index })), so omitting totalMedia in this reset won’t leave stale totalMedia—it becomes undefined.
  • The same setGamesIndex({ exists: false, ... totalFiles: 0 }) reset literal is duplicated in src/components/ConnectionProvider.tsx and src/routes/-pages/Search.tsx (no corresponding reset literal found in src/components/MediaDatabaseCard.tsx). Extracting a shared constant/helper would keep them in sync.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ConnectionProvider.tsx` around lines 597 - 608, The reset
block in setGamesIndex (used in ConnectionProvider and duplicated in Search)
should be deduplicated into a shared constant/helper (e.g., DEFAULT_GAMES_INDEX
or buildDefaultGamesIndex()) and imported/used from both places; also make the
reset explicit about IndexResponse.totalMedia semantics by either including
totalMedia: undefined (to document that it is intentionally cleared) or setting
a specific numeric default if you want 0, and update the setGamesIndex(...) call
in the isExpectedMediaDatabaseError handler to use that shared constant instead
of the duplicated literal.
src/lib/coreApi.ts (1)

101-117: 💤 Low value

Consider adding structured metadata to warning logs.

While expected errors are correctly downgraded to logger.warn, the warning call doesn't include structured metadata (category, action). Adding this context would improve filtering and debugging, even for expected failures.

♻️ Enhanced warning with metadata
 function logMediaApiFailure(
   label: string,
   action: string,
   error: unknown,
   severity: "error" | "warning" = "error",
 ): void {
   if (isExpectedMediaDatabaseError(error)) {
-    logger.warn(`${label}:`, error);
+    logger.warn(`${label}:`, error, {
+      category: "api",
+      action,
+    });
     return;
   }

   logger.error(`${label}:`, error, {
     category: "api",
     action,
     severity,
   });
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/coreApi.ts` around lines 101 - 117, The warning branch in
logMediaApiFailure currently calls logger.warn without structured metadata;
update the branch that checks isExpectedMediaDatabaseError(error) so it calls
logger.warn with the same metadata keys used by logger.error (include category:
"api" and action and severity) to ensure warnings carry the same context for
filtering and debugging; keep the existing message and error object and set
severity to "warning".
src/components/MediaDatabaseCard.tsx (1)

144-195: 💤 Low value

generateError is set on cancel/resume failure but never cleared on success.

handleUpdateDatabase clears generateError (Line 114) before retrying, but handleCancelUpdate/handleResumeUpdate only set it. A prior inline error can linger after a subsequent successful cancel/resume. Low likelihood since these handlers only run during indexing, but clearing on entry keeps the inline message consistent.

♻️ Optional: clear stale error on cancel/resume entry
   const handleCancelUpdate = async () => {
     setCancelRequested(true);
+    setGenerateError(null);
     try {
   const handleResumeUpdate = async () => {
     setResumeRequested(true);
+    setGenerateError(null);
     try {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/MediaDatabaseCard.tsx` around lines 144 - 195, The handlers
handleCancelUpdate and handleResumeUpdate currently set generateError on
failures but never clear it on entry, allowing stale error messages to persist
after a later successful action; modify both functions to clear the
generateError state at the start (e.g., call setGenerateError(null) or the
appropriate empty value) before setting setCancelRequested/setResumeRequested
and performing the API call, so any previous error is removed when a new
cancel/resume is attempted.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/__tests__/unit/components/ConnectionProvider.test.tsx`:
- Around line 86-89: The test mock for isExpectedMediaDatabaseError is doing
case-sensitive matching; update the predicate (isExpectedMediaDatabaseError) to
first assert the error is an Error and then convert error.message to lowercase
(e.g. const msg = (error as Error).message.toLowerCase()) before checking
msg.includes("no such table: dbconfig") || msg.includes("method not found") so
it mirrors the production case-insensitive logic used in coreApi.

In `@src/__tests__/unit/components/MediaDatabaseCard.test.tsx`:
- Around line 17-22: The test mocks for isMissingMediaDatabaseSetupError and
isExpectedMediaDatabaseError perform case-sensitive string checks; update them
to mirror production by normalizing the error message to lowercase before
matching (e.g., cast error to Error, compute const msg = (error instanceof Error
&& error.message) ? error.message.toLowerCase() : ""; then use msg.includes("no
such table: dbconfig") and msg.includes("method not found") in
isMissingMediaDatabaseSetupError and isExpectedMediaDatabaseError respectively)
so the predicates behave case-insensitively like the production implementation.

In `@src/__tests__/unit/routes/create.search.test.tsx`:
- Around line 53-56: The test mock for isExpectedMediaDatabaseError is doing
case-sensitive string matching; update it to normalize the error message to
lowercase (or use case-insensitive matching) before checking substrings so it
mirrors the production implementation in src/lib/coreApi.ts (e.g., call
.toString().toLowerCase() on the error or error.message and then check for "no
such table: dbconfig" and "method not found"); ensure the predicate still
accepts unknown errors but performs case-insensitive substring checks as in
production.

In `@src/lib/coreApi.ts`:
- Around line 78-85: In isUnsupportedMediaApiError, remove the redundant
instanceof CoreApiError branch (the check "error instanceof CoreApiError &&
message.includes('method not found')") since message.includes('method not
found') already covers it; then verify and correct the literal "query or system
is required" used in the predicate (or, better, switch to checking a stable
error code/property on CoreApiError if available) so that
getErrorMessage(error).toLowerCase() is compared against the exact
backend/contract message or a canonical error code instead of an unverified
substring.

---

Nitpick comments:
In `@src/components/ConnectionProvider.tsx`:
- Around line 597-608: The reset block in setGamesIndex (used in
ConnectionProvider and duplicated in Search) should be deduplicated into a
shared constant/helper (e.g., DEFAULT_GAMES_INDEX or buildDefaultGamesIndex())
and imported/used from both places; also make the reset explicit about
IndexResponse.totalMedia semantics by either including totalMedia: undefined (to
document that it is intentionally cleared) or setting a specific numeric default
if you want 0, and update the setGamesIndex(...) call in the
isExpectedMediaDatabaseError handler to use that shared constant instead of the
duplicated literal.

In `@src/components/MediaDatabaseCard.tsx`:
- Around line 144-195: The handlers handleCancelUpdate and handleResumeUpdate
currently set generateError on failures but never clear it on entry, allowing
stale error messages to persist after a later successful action; modify both
functions to clear the generateError state at the start (e.g., call
setGenerateError(null) or the appropriate empty value) before setting
setCancelRequested/setResumeRequested and performing the API call, so any
previous error is removed when a new cancel/resume is attempted.

In `@src/lib/coreApi.ts`:
- Around line 101-117: The warning branch in logMediaApiFailure currently calls
logger.warn without structured metadata; update the branch that checks
isExpectedMediaDatabaseError(error) so it calls logger.warn with the same
metadata keys used by logger.error (include category: "api" and action and
severity) to ensure warnings carry the same context for filtering and debugging;
keep the existing message and error object and set severity to "warning".

In `@src/routes/-pages/Search.tsx`:
- Line 13: The import in Search.tsx uses the .ts extension which is inconsistent
with other imports (e.g., ConnectionProvider.tsx); update the import statement
that currently reads "`@/lib/coreApi.ts`" to "`@/lib/coreApi`" so it matches the
repo style and tsconfig setting, and run a quick search for any other imports
with the .ts extension of coreApi to normalize them as well.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 12008a4a-2925-4543-80b7-409667c5bbcb

📥 Commits

Reviewing files that changed from the base of the PR and between 8cbc0b7 and ae8932d.

📒 Files selected for processing (10)
  • src/__tests__/unit/components/ConnectionProvider.test.tsx
  • src/__tests__/unit/components/MediaDatabaseCard.test.tsx
  • src/__tests__/unit/coreApi.api-contract.test.ts
  • src/__tests__/unit/routes/create.search.test.tsx
  • src/components/ConnectionProvider.tsx
  • src/components/MediaDatabaseCard.tsx
  • src/lib/coreApi.ts
  • src/lib/featureGates.ts
  • src/routes/-pages/Search.tsx
  • src/translations/en-US.json

Comment thread src/__tests__/unit/components/ConnectionProvider.test.tsx Outdated
Comment thread src/__tests__/unit/components/MediaDatabaseCard.test.tsx Outdated
Comment thread src/__tests__/unit/routes/create.search.test.tsx Outdated
Comment thread src/lib/coreApi.ts
@wizzomafizzo
wizzomafizzo merged commit 9f7bbb4 into main Jun 3, 2026
6 checks passed
@wizzomafizzo
wizzomafizzo deleted the fix/issue-143-media-db-degradation branch June 3, 2026 04:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve handling for unsupported or failing media database APIs

1 participant