Skip to content

fix(admin): resolve image upload race condition and premature cleanup#291

Merged
lyzno1 merged 4 commits intoiflabx:mainfrom
pixelsama:fix/image-upload-dialog-feedback
Oct 14, 2025
Merged

fix(admin): resolve image upload race condition and premature cleanup#291
lyzno1 merged 4 commits intoiflabx:mainfrom
pixelsama:fix/image-upload-dialog-feedback

Conversation

@pixelsama
Copy link
Contributor

Important

  1. Read CONTRIBUTING.md
  2. Ensure issue exists and you're assigned
  3. Link correctly: Fixes #<issue number>

What & Why

What: Fixed race condition in image upload cleanup logic that caused newly uploaded images to be deleted prematurely.

Why: The auto-cleanup functionality was running before the save operation completed, causing it to analyze the old database state and incorrectly identify newly uploaded images as "unused", deleting them from storage before they could be properly saved.

Fixes #290

Pre-PR Checklist

Run these:

  • pnpm type-check
  • pnpm format:check
  • pnpm lint
  • pnpm build
  • pnpm i18n:check (if applicable)

Type

  • 🐛 Bug fix
  • ✨ Feature
  • 💥 Breaking change
  • 📚 Docs
  • ♻️ Refactor
  • ⚡ Performance

Changes

Bug Fix (commit 92b9c31)

  • Moved cleanup logic: Relocated image cleanup from about-editor.tsx to page.tsx handleSave function
  • Fixed timing: Changed cleanup to run after successful save instead of before
  • Prevented data loss: Ensured images are only cleaned up after content is safely saved to database

Refactoring (commit 463ed3e)

  • Extracted helper function: Created cleanupUnusedImagesAfterSave to eliminate code duplication between About and Home page handlers
  • Improved user feedback: Replaced console.log with toast notifications showing cleanup results
  • Added i18n support: Added messages.cleanupImages translation key with plural support
  • Better UX: Users now see "Configuration saved successfully (3 unused images removed)" message
  • Removed dead code: Cleaned up commented-out cleanup code from about-editor component

Technical Details

Root Cause

The cleanup logic in about-editor.tsx was being called during the save process but before the actual database update completed. This created a race condition where:

  1. User uploads image → Supabase Storage ✅
  2. Component state updated locally ✅
  3. User clicks save
  4. Cleanup analyzes old database state
  5. New image marked as "unused" ❌
  6. Image deleted from storage ❌
  7. Database updated with broken reference ❌

Solution

// Before: Cleanup before save (race condition)
if (user?.id) {
  await cleanupUnusedImages(...); // Uses old state!
}
await TranslationService.updateAboutPageTranslations(...);

// After: Cleanup after save (safe)
await TranslationService.updateAboutPageTranslations(...);
if (user?.id) {
  await cleanupUnusedImages(...); // Uses new state ✅
}

Files Changed

  • app/admin/content/page.tsx - Main fix and refactoring
  • components/admin/content/about-editor.tsx - Removed outdated cleanup code
  • messages/en-US.json - Added cleanup feedback translation

Testing

  • Verified image upload no longer deletes newly uploaded images
  • Confirmed cleanup still removes truly unused images after save
  • Tested with both About and Home page editors
  • Verified toast notifications display correct message
  • Checked i18n plural forms work correctly

Fixes two critical issues preventing uploaded images from displaying:

1. Race condition in onUploadSuccess callback
   - Previously called handleInputChange twice sequentially
   - Second call used stale component.props, overwriting first update
   - Fixed by updating both src and _imagePath in single onPropsChange call

2. Auto-cleanup deleting newly uploaded images
   - cleanupUnusedImages triggered 100ms after upload via debouncedSave
   - Component state not yet updated with new _imagePath
   - Cleanup logic incorrectly identified new image as unused
   - Temporarily disabled auto-cleanup to prevent premature deletion

Additional improvements:
- Added 1.2s delay before closing upload dialog to show success state
- Removed all debug console.log statements for cleaner output
- Removed unused imports (createClient, useState, cleanupUnusedImages)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Oct 5, 2025

@pixelsama is attempting to deploy a commit to the zhang's projects Team on Vercel.

A member of the Team first needs to authorize it.

@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Oct 5, 2025
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @pixelsama, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical bug where newly uploaded images were being deleted due to a race condition in the cleanup process. Previously, the cleanup ran before the database save completed, leading to incorrect identification of new images as "unused." The changes refactor the cleanup mechanism to run post-save, ensuring that only genuinely unused images are removed, thereby preventing data loss and enhancing the reliability of content management. Additionally, the user experience is improved with clearer feedback on cleanup operations.

Highlights

  • Race Condition Fix: Resolved a critical race condition that caused newly uploaded images to be prematurely deleted during content save operations.
  • Cleanup Timing Adjustment: Relocated the image cleanup logic to execute after content has been successfully saved to the database, ensuring data consistency and preventing data loss.
  • Refactored Cleanup Logic: Extracted the image cleanup functionality into a reusable helper function, cleanupUnusedImagesAfterSave, to reduce code duplication and improve maintainability across different content editors.
  • Enhanced User Feedback: Implemented toast notifications to inform users about the number of unused images removed after a successful save, providing clearer feedback on cleanup operations.
  • Internationalization Support: Added i18n support for the image cleanup success message, including pluralization for accurate display of image counts.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@dosubot dosubot bot added type:bug Something is not working; user-visible defect. type:refactor Internal code improvements without behavior change. labels Oct 5, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request effectively resolves a critical race condition by ensuring image cleanup occurs after the database save operation completes. The refactoring to centralize cleanup logic, extract a helper function, and improve user feedback with toast notifications are all excellent improvements. My review focuses on further enhancing maintainability by addressing code duplication and removing dead code.

@vercel
Copy link

vercel bot commented Oct 6, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
agentif-ui Ready Ready Preview Comment Oct 6, 2025 7:50am

lyzno1
lyzno1 previously approved these changes Oct 6, 2025
@dosubot dosubot bot added the lgtm Looks good to me; approved by a reviewer. label Oct 6, 2025
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Oct 7, 2025
@pixelsama pixelsama force-pushed the fix/image-upload-dialog-feedback branch from 5c459df to 3b4d859 Compare October 7, 2025 09:39
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels Oct 7, 2025
…tructure

- Add user feedback for image cleanup failures with toast warning
- Refactor duplicated section collection logic into shared helper function
- Remove commented-out dead code from about-editor
- Restructure image-upload-dialog into modular directory structure
- Replace img tag with Next.js Image component for better performance
- Add i18n support for cleanup failure messages (en-US, zh-CN)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@pixelsama pixelsama force-pushed the fix/image-upload-dialog-feedback branch from 3b4d859 to 237707b Compare October 7, 2025 09:43
@dosubot dosubot bot removed the lgtm Looks good to me; approved by a reviewer. label Oct 7, 2025
Consolidate ImageUploadDialog component by merging image-upload-dialog.tsx
directly into index.tsx, removing unnecessary indirection layer.

Changes:
- Merge image-upload-dialog.tsx content into index.tsx
- Remove redundant index.ts export file
- Maintain all existing functionality and exports
- No breaking changes to import paths

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@dosubot dosubot bot added the lgtm Looks good to me; approved by a reviewer. label Oct 14, 2025
@lyzno1 lyzno1 merged commit 818f618 into iflabx:main Oct 14, 2025
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm Looks good to me; approved by a reviewer. size:L This PR changes 100-499 lines, ignoring generated files. type:bug Something is not working; user-visible defect. type:refactor Internal code improvements without behavior change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(admin): Image upload race condition causes premature cleanup

2 participants