Skip to content

[stable32] Handle duplicate key on trash unique constraint during concurrent deletes#4497

Merged
provokateurin merged 3 commits intostable32from
backport/4496/stable32
Mar 12, 2026
Merged

[stable32] Handle duplicate key on trash unique constraint during concurrent deletes#4497
provokateurin merged 3 commits intostable32from
backport/4496/stable32

Conversation

@backportbot
Copy link

@backportbot backportbot bot commented Mar 10, 2026

Backport of #4496

Warning, This backport's changes differ from the original and might be incomplete ⚠️

Todo

  • Review and resolve any conflicts
  • Amend HEAD commit to remove the line stating to skip CI

Learn more about backports at https://docs.nextcloud.com/server/stable/go.php?to=developer-backports.

@backportbot backportbot bot requested review from i2h3 and provokateurin March 10, 2026 10:02
@backportbot backportbot bot 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
@backportbot backportbot bot added this to the Nextcloud 32 milestone Mar 10, 2026
@i2h3 i2h3 marked this pull request as ready for review March 10, 2026 11:19
@i2h3 i2h3 enabled auto-merge March 10, 2026 11:20
@provokateurin
Copy link
Member

#4498 (comment)

@i2h3 i2h3 force-pushed the backport/4496/stable32 branch from 9e25d6c to e6f352c Compare March 11, 2026 08:25
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 <iva.horn@nextcloud.com>
i2h3 and others added 3 commits March 12, 2026 09:56
…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 <noreply@anthropic.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
- 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 <noreply@anthropic.com>

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
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 <iva.horn@nextcloud.com>
@i2h3 i2h3 force-pushed the backport/4496/stable32 branch from dda3bcc to 4e17145 Compare March 12, 2026 08:56
@i2h3
Copy link
Contributor

i2h3 commented Mar 12, 2026

@provokateurin I have no idea about these Cypress actions or how to fix it. Can you help?

@provokateurin
Copy link
Member

Hi, one of them is always failing, we can ignore that. The other one is unexpected, so I just restarted it again.

@i2h3 i2h3 disabled auto-merge March 12, 2026 13:06
@i2h3
Copy link
Contributor

i2h3 commented Mar 12, 2026

@provokateurin Do they need to pass?

@provokateurin
Copy link
Member

No, expected to fail unfortunately.

@provokateurin provokateurin merged commit 690b973 into stable32 Mar 12, 2026
56 of 64 checks passed
@provokateurin provokateurin deleted the backport/4496/stable32 branch March 12, 2026 15:18
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