Skip to content

intoduce new async_slow queue for image deletion - #2199

Open
blued-gear wants to merge 13 commits into
mainfrom
new/async_slow
Open

blued-gear wants to merge 13 commits into
mainfrom
new/async_slow

Conversation

@blued-gear

Copy link
Copy Markdown
Collaborator

On some platforms the deletion of many images when a user gets deleted takes quite a while. To decouple the deletion from the transaction which removes the user, this PR adds a new queue and new message for this job.

@blued-gear
blued-gear marked this pull request as ready for review August 5, 2026 20:54
@blued-gear

Copy link
Copy Markdown
Collaborator Author

I reworked the new code to lower the chance of race conditions between entity and file deletions.

Also, the tests now cover the MessageHandler.

@melroy89 melroy89 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Found three correctness issues in the image-deletion flow.

Comment thread src/MessageHandler/DeleteImageV2Handler.php

foreach ($filesToDelete as $path) {
try {
$this->imageManager->remove($path);

@melroy89 melroy89 Sep 9, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Image::filePath is nullable, and both message factories can therefore put a null value in this batch. When that value reaches ImageManagerInterface::remove(string), PHP throws a TypeError. The current catch (\Exception) does not catch it because TypeError implements Throwable, not Exception. The handler then fails and retries instead of continuing with the remaining images.

A simple guard keeps null paths away from the string-only API:

foreach ($filesToDelete as $path) {
    if (null === $path) {
        continue;
    }

    try {
        $this->imageManager->remove($path);
    } catch (\Exception $e) {
        // existing logging
    }
}

It would also help to stop adding null paths to $filesToDelete in the first place, but the removal boundary should still be safe because the incoming message may already contain null.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is this done..?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It is because if the path is null, then the image is skipped now. If the image was not referenced the entity in the db got deleted earlier as well

Comment thread src/MessageHandler/DeleteUserHandler.php Outdated
@melroy89
melroy89 self-requested a review September 9, 2026 15:32
@melroy89
melroy89 dismissed their stale review September 15, 2026 14:15

I don't want to block PRs

@melroy89 melroy89 added the enhancement New feature or request label Sep 18, 2026

@BentiGorlich BentiGorlich left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It looks good to me. What I don't understand is why you're keeping the old message and the old handler. Either it is a v2 or it is a special handler for big batches, which the name should reflect

Comment thread src/Message/DeleteImageMessage.php Outdated
use App\Message\Contracts\AsyncMessageInterface;

/**
* Attempts to delete the image entity from the database, but not the file from storage.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That is not correct... The handler has this at the bottom:

    if ($image?->filePath) {
        $this->imageManager->remove($image->filePath);
    }

@blued-gear

Copy link
Copy Markdown
Collaborator Author

What I don't understand is why you're keeping the old message and the old handler. Either it is a v2 or it is a special handler for big batches, which the name should reflect

It is a V2. I kept the old Message version because it is to be expected that queues are not empty when admins update their Mbin version. Then Symfony would not be able to deserialize the old messages, and we would lose data (data here means desired actions).
There are many more usages of the old version, which I would like to keep until the V2 has shown to be effective in prod.

@BentiGorlich

Copy link
Copy Markdown
Member

CI is failing with this error:

Fatal error: Cannot apply #[\Deprecated] to class App\Message\DeleteImageMessage in /__w/mbin/mbin/src/Message/DeleteImageMessage.php on line 13

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants