skip to Main Content

Im playing around with defer in laravel. I have this:

Route::get('testing', function () {
    defer(function(){
        //          sleep(3);
        Log::info('sleeping');
    })
        ->always(); // Will always run defer once executed

    return 'Rtoufasdfa';
});

Im getting this in my sail terminal.

PHP Fatal error:  Uncaught SwooleError: API must be called in the coroutine in /var/www/html/routes/web.php:94
  Stack trace:
2024-11-08 23:15:05,688 INFO reaped unknown pid 1093 (exit status 255)
 2024-11-08 23:15:05,688 INFO reaped unknown pid 1094 (exit status 255)
 #0 /var/www/html/routes/web.php(94): defer()

anyone familiar with defer whove ran into this issue?

2

Answers


  1. This means it looks like defer() requires a coroutine context, not available in standard Laravel routes.

    If one needs to run some tasks at the end of a request,

    try using register_shutdown_function since this function works outside coroutines:

    Route::get('testing', function () {
        register_shutdown_function(function() {
            Log::info('sleeping');
        });
    
        return 'Rtoufasdfa'; 
    });
    
    Login or Signup to reply.
  2. The error SwooleError: API must be called in the coroutine indicates that the defer function is being called outside of a Swoole coroutine context. Swoole’s defer function is designed to run cleanup tasks at the end of a coroutine, so it needs to be called within a coroutine.

    In Laravel, if you’re using Sail with Swoole, your code execution might not always be in a coroutine by default, especially in route closures. To solve this issue, you can make sure your code runs inside a coroutine.

    Here’s how you can wrap your code inside a coroutine for testing purposes:

    use SwooleCoroutine;
    
    Route::get('testing', function () {
        Coroutinerun(function () {
            defer(function () {
                Log::info('sleeping');
            });
    
            // Your main code logic here
            return 'Rtoufasdfa';
        });
    });
    

    If you need a more permanent solution for using coroutines within a controller or other parts of the application, you may want to use a Swoole-compatible package, such as swooletw/laravel-swoole, which can handle coroutine context automatically. Then, define your logic within a controller, ensuring it’s compatible with Swoole’s coroutine system.

    With this approach, the code in defer will execute correctly inside a coroutine, and the always() call should work as expected.

    Let me know if this helps resolve your error!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search