Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Handle duplicate key on trash unique constraint during concurrent deletes#4496

Merged
i2h3 merged 2 commits into
masterfrom
i2h3/fix/trash-unique-constraint-violation
Mar 10, 2026
Merged

Handle duplicate key on trash unique constraint during concurrent deletes#4496
i2h3 merged 2 commits into
masterfrom
i2h3/fix/trash-unique-constraint-violation

Conversation

@i2h3
Copy link
Copy Markdown
Contributor

@i2h3 i2h3 commented Mar 10, 2026

Replaces #4488 which was already approved but could not be merged due to failing cypress actions which do not work with forked repositories.

i2h3 and others added 2 commits March 10, 2026 09:49
…t deletes

The unique constraint on oc_group_folders_trash (folder_id, name,
deleted_time) uses second-granularity timestamps. When multiple files
with the same base name inside the same group folder are deleted within
the same second (e.g. by the desktop client issuing bulk DELETEs), the
INSERT in TrashManager::addTrashItem() fails with a unique constraint
violation. Because the file has already been physically moved to trash
storage before the INSERT, the failed DB record leaves the file
orphaned β€” resulting in data loss.

Insert the trash record before moving the file, using a for-loop that
retries with an incremented deleted_time on constraint collision. This
way the on-disk trash name is constructed from the confirmed timestamp
and no renames are needed. If the subsequent file move fails, the DB
record is cleaned up.

This follows the existing pattern in VersionsBackend.php for handling
the same class of constraint violation.

Fixes: #4014

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: Iva Horn <[email protected]>
- Wrap moveFromStorage() in try/catch to clean up the DB record when
  the move throws an exception (not just when it returns false)
- Fix test: use assertCount on full trash list instead of filtering by
  getName() which returns the trash filename with .d suffix
- Make test deterministic by waiting for a new-second boundary before
  both moveToTrash() calls so they always land in the same second

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: Iva Horn <[email protected]>
@i2h3 i2h3 self-assigned this Mar 10, 2026
@i2h3 i2h3 added bug 3. to review Items that need to be reviewed needs review Needs confirmation this is still happening or relevant (or possible duplicate TBD) labels Mar 10, 2026
@i2h3
Copy link
Copy Markdown
Contributor Author

i2h3 commented Mar 10, 2026

/backport to stable33

@i2h3
Copy link
Copy Markdown
Contributor Author

i2h3 commented Mar 10, 2026

/backport to stable32

Copy link
Copy Markdown
Member

@provokateurin provokateurin left a comment

Choose a reason for hiding this comment

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

Nice, thanks!

@i2h3 i2h3 merged commit a2f6ff3 into master Mar 10, 2026
106 of 110 checks passed
@i2h3 i2h3 deleted the i2h3/fix/trash-unique-constraint-violation branch March 10, 2026 10:02
i2h3 added a commit that referenced this pull request Mar 11, 2026
The original PR #4496 targeting **master** already includes the `private TrashManager $trashManager;` property declaration and the `use` import. The diff shows it properly adds both.

The backport PR #4497 **lost the property declaration** during the backport process. The PR description even warns about this: "This backport's changes differ from the original and might be incomplete."

What likely happened: the `master` branch and `stable32` branch have slightly different property orderings or surrounding context in `TrashBackendTest.php` (e.g., `master` doesn't have the `ACLManager` property, or they're in a different order). When the automated backport tool cherry-picked the changes, the hunk adding `private TrashManager $trashManager;` failed to apply cleanly and was silently dropped, while the code in `setUp()` and the new test method that *uses* `$this->trashManager` did apply β€” resulting in the mismatch.

Signed-off-by: Iva Horn <[email protected]>
i2h3 added a commit that referenced this pull request Mar 12, 2026
The original PR #4496 targeting **master** already includes the `private TrashManager $trashManager;` property declaration and the `use` import. The diff shows it properly adds both.

The backport PR #4497 **lost the property declaration** during the backport process. The PR description even warns about this: "This backport's changes differ from the original and might be incomplete."

What likely happened: the `master` branch and `stable32` branch have slightly different property orderings or surrounding context in `TrashBackendTest.php` (e.g., `master` doesn't have the `ACLManager` property, or they're in a different order). When the automated backport tool cherry-picked the changes, the hunk adding `private TrashManager $trashManager;` failed to apply cleanly and was silently dropped, while the code in `setUp()` and the new test method that *uses* `$this->trashManager` did apply β€” resulting in the mismatch.

Signed-off-by: Iva Horn <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Items that need to be reviewed bug needs review Needs confirmation this is still happening or relevant (or possible duplicate TBD)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants