'"RuntimeException: a facade root has not been set"

I'm having an issue in a Laravel Zero project I'm working on. I'm working on a command that handles direct file transfers between 2 disks—1 SFTP and another local.

I have configured both correctly and tested that I'm able to transfer files between them using the Storage code below. My issue pops up when I try to do this using the spatie/async package to create a pool of concurrent transfers (or maybe just the way I'm trying to do it).

$pool = Pool::create()
        ->concurrency($limit);

$progress = $this->output->createProgressBar($file_list);

if(!Storage::disk('local')->exists($local_folder_path)) {
    Storage::disk('local')->makeDirectory($local_folder_path);
}

foreach($file_list as $filename => $remote_path) {
    $pool->add(function() use ($remote_path, $filename, $local_folder_path) {
        Storage::disk('local')
            ->writeStream(
                "{$local_folder_path}/{$filename}",
                 Storage::disk('remote')->readStream($remote_path)
            );

        return $filename;
    })->then(function($filename) use (&$progress) {
        $this->info("{$filename} downloaded");
        $progress->advance();
    })->catch(function($exception) {
        $this->error($exception);
    });
}

$pool->wait();
$progress->finish();

By the way, the error, RuntimeException: a facade root has not been set, is being printed to my console via the catch() handler for the first item in the pool. I did discover that much.

I've searched for answers to this issue, but all of the articles and other SO/Stack Exchange postings I've come across didn't seem even similar to whatever's causing my issue.

Thanks in advance for any help.



Solution 1:[1]

The problem is that your callback (child process) is running without any setup.

A Task is useful in situations where you need more setup work in the child process. Because a child process is always bootstrapped from nothing, chances are you'll want to initialise eg. the dependency container before executing the task.

The facades are setup by the kernel that runs the \LaravelZero\Framework\Bootstrap\RegisterFacades::class.

You can create an instance of the kernel and run the bootstrap method to have your facades setup properly.

$pool->add(function() use ($remote_path, $filename, $local_folder_path) {
        $app = require __DIR__.'/../../bootstrap/app.php';

        $kernel = $app->make(\Illuminate\Contracts\Console\Kernel::class);

        $kernel->bootstrap();

        Storage::disk('local')
            ->writeStream(
                "{$local_folder_path}/{$filename}",
                 Storage::disk('remote')->readStream($remote_path)
            );

        return $filename;
    })

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Chin Leung