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

Acorn scheduler is not loading wordpress correctly #383

Open
tgeorgel opened this issue Jul 12, 2024 · 4 comments
Open

Acorn scheduler is not loading wordpress correctly #383

tgeorgel opened this issue Jul 12, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@tgeorgel
Copy link

Version

v4.2.2

What did you expect to happen?

I'm using Acorn in combinaison with Radicle.

I did register a Kernel instance :

\Roots\bootloader()->boot(function ($app) {
    $app->singleton(
        \Illuminate\Contracts\Console\Kernel::class,
        \App\Console\Kernel::class
    );
});

Which provides schedules :

namespace App\Console;

use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Foundation\Application;
use Roots\Acorn\Console\Kernel as RootsKernel;
use Illuminate\Console\Scheduling\Schedule;

class Kernel extends RootsKernel
{
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('debug:dump')->everySecond();
    }

    public function __construct(Application $app, Dispatcher $events)
    {
        if (! defined('ARTISAN_BINARY')) {
            define('ARTISAN_BINARY', dirname(__DIR__, 2) . '/vendor/roots/acorn/bin/acorn');
        }

        $this->app = $app;
        $this->events = $events;

        // Make sure our schedules are getting registered
        $this->app->extend(Schedule::class, function ($app) {
            return tap(new Schedule($this->scheduleTimezone()), function ($schedule) {
                $this->schedule($schedule->useCache($this->scheduleCache()));
            });
        });

        $this->app->booted(function () {
            $this->defineConsoleSchedule();
        });
    }
}

Schedules are working nicely, but the load of Wordpress is not complete.
For example, If I would want to get the permalink of a page inside my command :

// App\Console\Commands\DebugDump

public function handle()
{
    ray(get_permalink(2));
}

When using WP-CLI, this works perfectly :

wp acorn debug:dump 

// http://site.test/my-page-name

But in the scheduler context, I get :

 wp acorn schedule:test

Running ['vendor/roots/acorn/bin/acorn' debug:dump] ................................................................................... 344ms DONE
  ⇂ '/opt/homebrew/Cellar/php@8.2/8.2.18/bin/php' 'vendor/roots/acorn/bin/acorn' debug:dump > '/dev/null' 2>&1
  
 // http://site.test/?page_id=2

What actually happens?

When running the scheduler with acorn, the acorn binary is called.

This binary loads wordpress and then expect acorn to boot on top :

require_once "{$rootPath}/{$composer['extra']['wordpress-install-dir']}/wp-blog-header.php";

Roots\Acorn\Bootloader::getInstance()->boot();

The seconds line nevers gets called.

What actually happens is that the wp-settings.php file is going to load the mu-plugins, which loads Acorn (00-acorn-boot.php), and the load of Acorn "captures" the "request", and so any code that should have run after the load of mu-plugins (inside wp-settings.php) won't run, including settings up default post_types and so on :

// file: wp-settings.php

// Load must-use plugins.
foreach ( wp_get_mu_plugins() as $mu_plugin ) {
    $_wp_plugin_file = $mu_plugin;
    include_once $mu_plugin; // <-- loading acorn will stop here.
    $mu_plugin = $_wp_plugin_file;
    do_action( 'mu_plugin_loaded', $mu_plugin );
}

/** Never reach this part */

/** ... */

create_initial_taxonomies();
create_initial_post_types();

/** ... */

This means that if I run a command with the scheduler :

 wp acorn schedule:test
  Running ['vendor/roots/acorn/bin/acorn' debug:dump] ................................................................................... 344ms DONE
  ⇂ '/opt/homebrew/Cellar/php@8.2/8.2.18/bin/php' 'vendor/roots/acorn/bin/acorn' debug:dump > '/dev/null' 2>&1

The debug:dump command won't be able to get a permalink (eg: get_permalink(1)) as the internal get_post_status_object() function could not return values because the core is not fully loaded.

Steps to reproduce

Create a Kernel class :

namespace App\Console;

use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Foundation\Application;
use Roots\Acorn\Console\Kernel as RootsKernel;
use Illuminate\Console\Scheduling\Schedule;

class Kernel extends RootsKernel
{
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('debug:dump')->everySecond();
    }

    public function __construct(Application $app, Dispatcher $events)
    {
        if (! defined('ARTISAN_BINARY')) {
            define('ARTISAN_BINARY', dirname(__DIR__, 2) . '/vendor/roots/acorn/bin/acorn');
        }

        $this->app = $app;
        $this->events = $events;

        // Make sure our schedules are getting registered
        $this->app->extend(Schedule::class, function ($app) {
            return tap(new Schedule($this->scheduleTimezone()), function ($schedule) {
                $this->schedule($schedule->useCache($this->scheduleCache()));
            });
        });

        $this->app->booted(function () {
            $this->defineConsoleSchedule();
        });
    }
}

Make sure to register the kernel class when booting acorn :

\Roots\bootloader()->boot(function ($app) {
    $app->singleton(
        \Illuminate\Contracts\Console\Kernel::class,
        \App\Console\Kernel::class
    );
});

Then, after creating a command which tries to display a permalink, test it thru the scheduler using wp acorn schedule:test.

System info

MacBook Air M1
MacOS Sonoma 14.5
PHP 8.2.18

Log output

No response

Please confirm this isn't a support request.

Yes

@tgeorgel tgeorgel added the bug Something isn't working label Jul 12, 2024
@mfr75
Copy link

mfr75 commented Oct 2, 2024

up

@RafaelKr
Copy link
Contributor

RafaelKr commented Oct 4, 2024

I also had a similar setup and noticed it would boot the Acorn Kernel AND my custom Kernel.

Maybe you can try to overwrite the implementation for \Roots\Acorn\Console\Kernel instead:

\Roots\bootloader()->boot(function ($app) {
    $app->singleton(
        \Roots\Acorn\Console\Kernel::class,
        \App\Console\Kernel::class
    );
});

// see comment below
// }, 0);

Also the Acorn boot priority was updated recently: https://github.com/roots/radicle/commit/5af169578560f6b1b7ec0879b4d4ce2d7842f25c

This is also something you could try.

Recently I got rid of overwriting the Kernel and moved my logic to a ServiceProvider instead. But I don't know if that's also possible for scheduling.

Details
<?php

declare(strict_types=1);

namespace App\Providers;

// [...]
use BabDev\ServerPushManager\Http\Middleware\ServerPush;
use Illuminate\Support\ServiceProvider;
use Roots\Acorn\Http\Kernel;

class WordPressOptimizationProvider extends ServiceProvider
{
    // [...]

    public function __construct($app)
    {
        parent::__construct($app);

        $app->extend(Kernel::class, function (Kernel $kernel) {
            // We need to add this first to make sure we're able to set headers
            return $kernel->prependMiddlewareToGroup('web', ServerPush::class);
        });
    }

    // [...]
}

@mfr75
Copy link

mfr75 commented Dec 3, 2024

still need help on this one

@retlehs
Copy link
Member

retlehs commented Dec 3, 2024

@mfr75 The first bump wasn't necessary, nor was the second one. Post on Roots Discourse if you want to hire someone from the community if you're looking for immediate help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants