Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cancel abilities to Deferred Callbacks #52816

Closed
wants to merge 5 commits into from
Closed

Add cancel abilities to Deferred Callbacks #52816

wants to merge 5 commits into from

Conversation

rbadillap
Copy link
Contributor

@rbadillap rbadillap commented Sep 17, 2024

Note

A PR was created with the purpose to mention the forget method in the documentation: laravel/docs#9902.

Hello Laravel team,

In this PR I'm adding capabilities to the new defer() helper to be cancelled.

What is defer()?

Check this announcement out.

Proposed change

Add the ability to cancel deferred callbacks before they are executed. This can be achieved in two ways:

Option 1: Cancelling by name

defer(fn() => performTask(), 'task-name');
// Later...
defer()->cancel('task-name');

Option 2: Cancelling directly

$task = defer(fn() => performTask());
// Later...
$task->cancel();

Important

I've opened a discussion thread about this topic here.

Recreation instructions

The best way to recreate this feature is by using routes.

Route::get('/500', function () {
    $a = defer(function () {
        usleep(microseconds: 250000);
        info(message: 'executing defer: a');
    }, name: 'a');

    $b = defer(function () {
        usleep(microseconds: 500000);
        info(message: 'executing defer: b');
    }, name: 'b');

    $c = defer(function () {
        usleep(microseconds: 750000);
        info(message: 'executing defer: c');
    }, name: 'c');

    $d = defer(function () {
        usleep(microseconds: 1000000);
        info(message: 'executing defer: d');
    }, name: 'd');

    $a->always()->cancel('a'); // this cancels $a
    $b->always();
    $c->always();
    $d->always(); // this never got cancelled

    // this cancels $b
    if ( true ) {
        $b->cancel();
    }

    // this cancels $c
    defer()->cancel('c');

    return response([ 'status' => '500'], 500);
});

The expected result of the code above is:
image

Pending

Depending on the feedback received and whether the community takes this approach positively, I need to complete this feature by adding:

  • Code and details about the feature
  • Test cases (?)
  • Documentation

Thanks,
Ronny

Copy link

Thanks for submitting a PR!

Note that draft PR's are not reviewed. If you would like a review, please mark your pull request as ready for review in the GitHub user interface.

Pull requests that are abandoned in draft may be closed due to inactivity.

@devajmeireles
Copy link
Contributor

I don't know about the format, but the cancel concept sounds pretty useful.

@rbadillap
Copy link
Contributor Author

I think this PR is ready for review.

All test cases are green, and don't see much more functionality to be added, keeping the more simple approach as possible.

ICYM, I've opened a discussion thread just in case you consider it necessary.
#52817

PD: sorry about the unverified commits, I fixed that in my last commit.
PD2: I'm aware about this PR: #52801, I don't see any particular impact on choosing which PR should be merged first, if you move defer to Support, I can do the changes real quick if necessary.

@rbadillap rbadillap marked this pull request as ready for review September 17, 2024 15:39
@taylorotwell
Copy link
Member

You can already defer()->forget('callback-name'); 👍

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.

3 participants