async icon indicating copy to clipboard operation
async copied to clipboard

Fatal error: Uncaught TypeError: call_user_func_array(): Argument #1 ($callback) must be a valid callback, no array or string given

Open iampedropiedade opened this issue 11 months ago • 1 comments

Hi. I was experimenting with Spatie/Async and I was able to have it working on a Symfony console Command. But if I grab the same code, adapt it and to run it without the Symfony framework, I get the following error:

1
Fatal error: Uncaught TypeError: call_user_func_array(): Argument #1 ($callback) must be a valid callback, no array or string given

#0 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/vendor/laravel/serializable-closure/src/Serializers/Native.php(91): call_user_func_array(NULL, Array)
#1 [internal function]: Laravel\SerializableClosure\Serializers\Native->__invoke()
#2 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/vendor/laravel/serializable-closure/src/SerializableClosure.php(48): call_user_func_array(Object(Laravel\SerializableClosure\Serializers\Native), Array)
#3 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/vendor/spatie/async/src/Runtime/ChildRuntime.php(26): Laravel\SerializableClosure\SerializableClosure->__invoke()
#4 {main} in /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/vendor/spatie/async/src/Output/SerializableException.php:29
Stack trace:
#0 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/vendor/spatie/async/src/Process/ParallelProcess.php(121): Spatie\Async\Output\SerializableException->asThrowable()
#1 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/vendor/spatie/async/src/Process/ProcessCallbacks.php(54): Spatie\Async\Process\ParallelProcess->resolveErrorOutput()
#2 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/vendor/spatie/async/src/Pool.php(246): Spatie\Async\Process\ParallelProcess->triggerError()
#3 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/vendor/spatie/async/src/Pool.php(363): Spatie\Async\Pool->markAsFailed(Object(Spatie\Async\Process\ParallelProcess))
#4 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/vendor/spatie/async/src/Pool.php(344): Spatie\Async\Pool->handleFinishedProcess(41131, 1)
#5 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/vendor/spatie/async/src/Pool.php(168): Spatie\Async\Pool->Spatie\Async\{closure}(20, Array)
#6 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/vendor/spatie/async/src/helpers.php(22): Spatie\Async\Pool->wait()
#7 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/index.php(57): await(Object(Spatie\Async\Pool))
#8 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/index.php(14): ParallelSumCommand->calculate(1)
#9 /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/index.php(69): ParallelSumCommand->execute()
#10 {main}
  thrown in /Users/pedropiedade/Documents/http/pedro/code-challenges/sums/vendor/spatie/async/src/Output/SerializableException.php on line 29

Here is the code:

include './vendor/autoload.php';

use Spatie\Async\Pool;

class ParallelSumCommand
{
    protected int $sum = 0;

    public function execute(): int
    {
        $test = $this->calculate(1);
        echo sprintf("The sum of all even numbers from %d to %d is %d", $test['min'], $test['max'], $test['sum']);
        echo sprintf("This sum took %d miliseconds to calculate using %d parallel threads\n", $test['time'], $test['channels']);

        $test = $this->calculate(5);
        echo sprintf("The sum of all even numbers from %d to %d is %d", $test['min'], $test['max'], $test['sum']);
        echo sprintf("This sum took %d miliseconds to calculate using %d parallel threads\n", $test['time'], $test['channels']);

        $test = $this->calculate(10);
        echo sprintf("The sum of all even numbers from %d to %d is %d", $test['min'], $test['max'], $test['sum']);
        echo sprintf("This sum took %d miliseconds to calculate using %d parallel threads\n", $test['time'], $test['channels']);

        $test = $this->calculate(20);
        echo sprintf("The sum of all even numbers from %d to %d is %d", $test['min'], $test['max'], $test['sum']);
        echo sprintf("This sum took %d miliseconds to calculate using %d parallel threads\n", $test['time'], $test['channels']);
        return 1;
    }

    protected function calculate(int $channels): array
    {
        $pool = Pool::create()->concurrency($channels);
        $rangeMin = 1;
        $rangeMax = 100000000;
        $currentMin = $rangeMin;
        $step = intval(($rangeMax - $rangeMin) / $channels);
        $start = microtime(true);
        $this->sum = 0;

        for ($i=0; $i <= $channels; $i++) {
            $currentMax = $currentMin + $step;
            $pool[] = async(function ()  use ($currentMin, $currentMax, $rangeMax) {
                $sum = 0;
                $max = min($currentMax, $rangeMax);
                for ($i=$currentMin; $i <= $max; $i++) {
                    if($i % 2 === 0) {
                        $sum += $i;
                    }
                }
                return $sum;
            })->then(function (int $output) {
                $this->sum += $output;
            });
            $currentMin = $currentMax + 1;
        }
        await($pool);
        $end = microtime(true);
        return [
            'min' => $rangeMin,
            'max' => $rangeMax,
            'channels' => $channels,
            'time' => ($end - $start) * 1000,
            'sum' => $this->sum
        ];
    }
}

(new ParallelSumCommand())->execute();

The calculate method is the exact same code in the Symfony and non-Symfony version, just the execute method that changes slightly. Is this some bug or am I doing something wrong?

iampedropiedade avatar Mar 27 '24 09:03 iampedropiedade