Skip to content

Conversation

@V4Vikaskumar
Copy link

@V4Vikaskumar V4Vikaskumar commented Dec 24, 2025

Summary

This PR fixes an issue where db_update_cluster() was unconditionally closing the database connection, even when the connection was provided by the caller.

This caused unexpected connection closures and crashes in transaction-based workflows.

What was changed

  • Added explicit ownership tracking for database connections.
  • Ensured that commit() and close() are only performed when the connection is created inside the function.
  • Preserved externally managed connections to maintain transaction integrity.

Why this is needed

db_update_cluster() supports being called within an external transaction context. Closing externally supplied connections breaks transactional behavior and results in runtime errors such as:

Summary

This PR fixes an issue where db_update_cluster() was unconditionally closing the database connection, even when the connection was provided by the caller.

This caused unexpected connection closures and crashes in transaction-based workflows.

What was changed

  • Added explicit ownership tracking for database connections.
  • Ensured that commit() and close() are only performed when the connection is created inside the function.
  • Preserved externally managed connections to maintain transaction integrity.

Why this is needed

db_update_cluster() supports being called within an external transaction context. Closing externally supplied connections breaks transactional behavior and results in runtime errors such as:

How it was tested

  • Executed multiple db_update_cluster() calls using a shared connection.
  • Verified that no errors occur and transactions complete successfully.

Checking

I run this command in python terminal and output is
Command : --

from app.database.face_clusters import db_update_cluster
import sqlite3
from app.config.settings import DATABASE_PATH

conn = sqlite3.connect(DATABASE_PATH)

db_update_cluster("test_id", "Test", conn)
db_update_cluster("test_id2", "Test2", conn)

conn.commit()
conn.close()

print("SUCCESS: db_update_cluster works correctly")

Before Check

checking before

After Check

After Check

Related Issue

Fixes #824

Summary by CodeRabbit

  • Bug Fixes

    • Improved stability of the onboarding flow with enhanced error handling for server connectivity checks and better state management during avatar selection and folder setup.
    • Prevented unintended behavior when components unmount during asynchronous operations.
    • Enhanced database connection handling for better resource management.
  • Documentation

    • Added comprehensive React Hooks Guidelines to help maintain code quality.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 24, 2025

📝 Walkthrough

Walkthrough

This PR addresses database connection lifecycle management in the backend and fixes React Hooks dependency issues across multiple onboarding components. The db_update_cluster function now conditionally commits and closes connections only when it owns the connection, preventing premature closure of externally-managed connections. Frontend onboarding steps update useEffect dependency arrays and add lifecycle guards to prevent stale effects and memory leaks.

Changes

Cohort / File(s) Summary
Backend Database Connection Fix
backend/app/database/face_clusters.py
Conditional commit/close logic: function now checks own_connection flag before committing or closing DB connections in finally block, preventing premature closure of externally-provided connections.
Frontend Onboarding Hooks Dependencies
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx, frontend/src/components/OnboardingSteps/FolderSetupStep.tsx, frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx
useEffect dependency arrays updated from [] to [dispatch, stepIndex], ensuring effects re-run when dependencies change. Each component now explicitly reads localStorage and guards step completion dispatch.
Frontend Server Check with Error Handling
frontend/src/components/OnboardingSteps/ServerCheck.tsx
Early returns added when loading states are true; error handling now shows info dialog before exit; dependency array expanded to [dispatch, stepIndex, ...] and includes all sync microservice query states.
Frontend Update Step with Mount Guard
frontend/src/components/OnboardingSteps/UpdateStep.tsx
Adds local isMount flag to guard against unmount-during-async-operation; tightens completion condition to only mark complete when mounted and no update present; dependency array updated to [dispatch, stepIndex, checkForUpdates].
Documentation React Hooks Guidelines
docs/frontend/state-management.md
New "React Hooks Guidelines" subsection added (duplicated in two locations) covering useEffect dependencies, stale closures, and ESLint rule compliance.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

bug, backend

Suggested reviewers

  • rahulharpal1603

Poem

🐰 A rabbit hops through code so fine,
Connections owned, or loaned—divine!
Hooks dance true with deps in place,
No stale closures cloud the race.
From mount guard walls, memory's grace! ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Multiple frontend changes to useEffect dependency arrays in OnboardingSteps components appear unrelated to the database connection fix specified in the title and linked issue. The frontend dependency array changes and documentation additions should be addressed in separate PRs focused on React Hooks guidelines rather than bundled with the database connection fix.
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: preventing externally managed database connections from being closed in db_update_cluster, which is the primary change in the backend code.
Linked Issues check ✅ Passed The PR addresses the core objective from issue #824 by adding connection ownership tracking to db_update_cluster, ensuring commit/close only occur for owned connections.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/components/OnboardingSteps/ServerCheck.tsx (1)

63-72: Fix: Add spaces after commas in dependency array.

For consistency, format as: [dispatch, stepIndex, ...] with spaces after each comma.

🔎 Proposed fix
   }, [
-    dispatch,
-    stepIndex,
+    dispatch,
+    stepIndex,
     mainBackendSuccess,
     mainBackendLoading,
     mainBackendError,
     syncMicroserviceSuccess,
     syncMicroserviceLoading,
     syncMicroserviceError,
   ]);
🧹 Nitpick comments (3)
backend/app/database/face_clusters.py (2)

186-208: Consider API consistency for parameter type.

The function accepts an optional conn (Connection) parameter, while other functions in this file like db_delete_all_clusters and db_insert_clusters_batch accept an optional cursor (Cursor) parameter. Both approaches work correctly, but having a consistent API across similar functions would improve developer experience and reduce confusion.

Consider aligning the parameter type in a future refactor, though this is not urgent and the current implementation functions correctly.


209-236: Add explicit error handling for consistency.

The function lacks an explicit except block with rollback, unlike similar functions in this file (db_delete_all_clusters and db_insert_clusters_batch). While SQLite automatically rolls back on connection close, explicit error handling improves code clarity and consistency.

🔎 Proposed refactor to add explicit error handling
     cursor = conn.cursor()
 
     try:
         # Build the update query dynamically based on provided parameters
         update_fields = []
         update_values = []
 
         if cluster_name is not None:
             update_fields.append("cluster_name = ?")
             update_values.append(cluster_name)
 
         if not update_fields:
             return False
 
         update_values.append(cluster_id)
 
         cursor.execute(
             f"UPDATE face_clusters SET {', '.join(update_fields)} WHERE cluster_id = ?",
             update_values,
         )
 
         updated = cursor.rowcount > 0
         if own_connection:
             conn.commit()
 
         return updated
+    except Exception:
+        if own_connection:
+            conn.rollback()
+        raise
     finally:
         if own_connection:
             conn.close()
docs/frontend/state-management.md (1)

239-246: Consider adding formatting guidelines for dependency arrays.

Since the code changes revealed consistent formatting issues (missing spaces after commas), consider adding a note about proper dependency array formatting:

- Format dependency arrays with spaces after commas: `[dispatch, stepIndex]`
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 917daff and 6804000.

⛔ Files ignored due to path filters (2)
  • frontend/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • backend/app/database/face_clusters.py
  • docs/frontend/state-management.md
  • frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx
  • frontend/src/components/OnboardingSteps/FolderSetupStep.tsx
  • frontend/src/components/OnboardingSteps/ServerCheck.tsx
  • frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx
  • frontend/src/components/OnboardingSteps/UpdateStep.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx (1)
frontend/src/features/onboardingSlice.ts (1)
  • markCompleted (31-42)
frontend/src/components/OnboardingSteps/UpdateStep.tsx (2)
frontend/src/features/loaderSlice.ts (2)
  • showLoader (17-20)
  • hideLoader (21-24)
frontend/src/features/onboardingSlice.ts (1)
  • markCompleted (31-42)
🔇 Additional comments (7)
backend/app/database/face_clusters.py (1)

229-230: LGTM! Core fix correctly addresses the connection lifecycle issue.

The conditional commit and close operations properly respect connection ownership:

  • When the function creates its own connection (own_connection=True), it commits and closes appropriately
  • When an external connection is provided (own_connection=False), the function preserves it for the caller to manage

This implementation successfully prevents premature closure of externally managed connections and maintains transaction integrity, directly addressing issue #824.

Also applies to: 234-235

frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx (1)

33-37: Verify behavior when stepIndex changes while localStorage state persists.

Similar to FolderSetupStep, if stepIndex changes while the component remains mounted and localStorage retains the 'themeChosen' flag, the effect will incorrectly mark the new step as completed.

Verify whether onboarding steps are unmounted between transitions or if the same component instance receives different stepIndex values.

frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx (1)

36-42: Verify behavior when stepIndex changes while localStorage state persists.

The effect marks stepIndex as completed when both localStorage values exist. If the component receives a new stepIndex while these localStorage items persist, it could skip the wrong step.

Verify the component lifecycle during onboarding navigation to ensure this scenario doesn't occur.

frontend/src/components/OnboardingSteps/UpdateStep.tsx (1)

26-44: LGTM: Mount guard pattern prevents memory leaks.

The isMount flag properly prevents state updates after component unmount, avoiding potential memory leaks and React warnings during async update checks. The cleanup function correctly resets the flag.

frontend/src/components/OnboardingSteps/ServerCheck.tsx (1)

38-58: LGTM: Early returns prevent redundant dispatches.

The early returns when loading (line 41) or on error (line 57) properly prevent the effect from continuing execution and dispatching conflicting actions. This is a clean pattern for managing the async health check states.

docs/frontend/state-management.md (1)

239-246: LGTM: Documentation aligns with implemented changes.

The React Hooks Guidelines clearly explain the reasoning behind the useEffect dependency updates made throughout the onboarding components. This will help maintain consistency in future development.

frontend/src/components/OnboardingSteps/FolderSetupStep.tsx (1)

33-37: This concern is not applicable to the current implementation.

The component architecture prevents the scenario described. When markCompleted(stepIndex) is dispatched (line 57), the Redux reducer updates both currentStepIndex AND currentStepName atomically (onboardingSlice.ts lines 40-41). The OnboardingStep component then switches which step component to render based on stepName (OnboardingStep.tsx lines 31-46). This causes FolderSetupStep to unmount entirely when transitioning to the next step, rather than remaining mounted with a new stepIndex prop. Additionally, once localStorage is set to 'true', the component returns null (line 65), preventing any further effect execution.

dispatch(markCompleted(stepIndex));
}
}, []);
}, [dispatch,stepIndex]);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix: Add space after comma in dependency array.

For consistency, format as: [dispatch, stepIndex] instead of [dispatch,stepIndex].

🔎 Proposed fix
-  }, [dispatch,stepIndex]);
+  }, [dispatch, stepIndex]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
}, [dispatch,stepIndex]);
}, [dispatch, stepIndex]);
🤖 Prompt for AI Agents
In frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx around line
42, the dependency array in the useEffect is missing a space after the comma:
change `[dispatch,stepIndex]` to `[dispatch, stepIndex]` to match project
formatting and consistency; update the array spacing and run/format to ensure
linting passes.

dispatch(markCompleted(stepIndex));
}
}, []);
}, [dispatch,stepIndex]);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix: Add space after comma in dependency array.

The dependency array should have proper spacing for consistency with coding standards: [dispatch, stepIndex] instead of [dispatch,stepIndex].

🔎 Proposed fix
-  }, [dispatch,stepIndex]);
+  }, [dispatch, stepIndex]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
}, [dispatch,stepIndex]);
}, [dispatch, stepIndex]);
🤖 Prompt for AI Agents
In frontend/src/components/OnboardingSteps/FolderSetupStep.tsx around line 37,
the dependency array in the useEffect is missing a space after the comma; update
the array to have a space for consistency and style (change
`[dispatch,stepIndex]` to `[dispatch, stepIndex]`) ensuring formatting matches
project linting and style rules.

dispatch(markCompleted(stepIndex));
}
}, []);
}, [dispatch,stepIndex]);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix: Add space after comma in dependency array.

Consistent with formatting standards, the dependency array should have proper spacing: [dispatch, stepIndex] instead of [dispatch,stepIndex].

🔎 Proposed fix
-  }, [dispatch,stepIndex]);
+  }, [dispatch, stepIndex]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
}, [dispatch,stepIndex]);
}, [dispatch, stepIndex]);
🤖 Prompt for AI Agents
In frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx around line
37, the dependency array currently reads "[dispatch,stepIndex]" missing a space
after the comma; update it to "[dispatch, stepIndex]" to match formatting
standards (add a single space after the comma in the dependency array).

return () => {
isMount = false;
}
}, [dispatch,stepIndex, checkForUpdates]);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix: Add spaces after commas in dependency array.

Format as: [dispatch, stepIndex, checkForUpdates] instead of [dispatch,stepIndex, checkForUpdates].

🔎 Proposed fix
-  }, [dispatch,stepIndex, checkForUpdates]);
+  }, [dispatch, stepIndex, checkForUpdates]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
}, [dispatch,stepIndex, checkForUpdates]);
}, [dispatch, stepIndex, checkForUpdates]);
🤖 Prompt for AI Agents
In frontend/src/components/OnboardingSteps/UpdateStep.tsx around line 45, the
dependency array in the useEffect hook is missing a space after the first comma;
change the array from [dispatch,stepIndex, checkForUpdates] to [dispatch,
stepIndex, checkForUpdates] to match project formatting and maintain consistent
spacing after commas.

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.

BUG: Connection leak in db_update_cluster() causes crashes in transaction-based operations

1 participant