bref icon indicating copy to clipboard operation
bref copied to clipboard

A note on config cache

Open yangm97 opened this issue 3 years ago • 8 comments

From Bref/Storage/Pre-generating the cache:

Pre-generating the cache

Some frameworks allow to pre-generate some caches. For example in Symfony the container can be compiled via bin/console cache:warmup, or in Laravel the config cache can be generated before deploying.

When possible this is the best solution: no generation will occur in production, and reading from the filesystem will be fast.

From Laravel/Configuration Caching (emphasis mine):

Once the configuration has been cached, the .env file will not be loaded and all calls to the env function will return null.

Now suppose you're using any AWS service which makes use of the $AWS_SESSION_TOKEN environment variable, pre-generating the config cache on deployment will miss runtime variables, which in turn makes them always return null.

This could confuse newcomers, as this gotcha isn't obvious and this strategy is actually highlighted as the "best solution".

Unless I'm missing some Laravel magic, guess the Bref docs need to be updated.

yangm97 avatar Aug 11 '20 14:08 yangm97

Hi, this is a very good point, Laravel is a bit special on this regard. We can probably improve the documentation here.

mnapoli avatar Aug 11 '20 20:08 mnapoli

Perhaps we could run artisan config:cache on the startup of the container? Don't believe the session token etc changes between invocations on the same container.

georgeboot avatar Dec 02 '20 18:12 georgeboot

They don't, but the filesystem is read-only so the cached config cannot be written at runtime.

mnapoli avatar Dec 02 '20 20:12 mnapoli

Laravel Vapor does this with route caching. I think the cache path is configurable, so we could simple point it to /tmp, right?

https://github.com/laravel/vapor-core/blob/24bee0a7d72964145bc162a5f4f386affb5d56fb/stubs/fpmRuntime.php#L58-L66

georgeboot avatar Dec 02 '20 20:12 georgeboot

Indeed, I'm not a huge fan of moving the whole storage directory to /tmp for the following reasons: https://github.com/brefphp/laravel-bridge/pull/9#issuecomment-672684462

Do you think it's possible to move only the config cache to /tmp? (instead of the whole storage directory)

mnapoli avatar Jan 15 '21 08:01 mnapoli

This is, as far as I am aware, currently not possible. Laravel exposes only a storage directory configurable.

We would have to PR the framework for this.

georgeboot avatar Jan 17 '21 15:01 georgeboot

This may be possible if you update the bootstrapper list early on.

I do this in a non-bref project so that I can insert a pre-env bootstraper (to allow moving of the env location) and a post-env bootstrapper (to dynamically change the storage location).

In the Kernel::__construct() I call an install function after the call to the parent constructor.

class Kernel {
  public function __construct(Application $app, Dispatcher $events)
    {
        parent::__construct($app, $events);
        Bootstrap::install($this->bootstrappers);
    }
}

class Bootstrap
{
    public static function install(array &$bootstrappers)
    {
        static::doInstall($bootstrappers, 0, BootstrapBeforeEnv::class);
        static::doInstall($bootstrappers, 1, BootstrapAfterEnv::class);
    }

    public static function doInstall(array &$bootstrappers, $position, $class_names)
    {
        if (is_string($class_names)) {
            $class_names = [$class_names];
        }

        $env_configure_index = array_search('Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables', $bootstrappers);
        if ($env_configure_index === false) {
            throw new \Exception('Can\'t see when environment is ready');
        }
        array_splice($bootstrappers, $env_configure_index + $position, 0, $class_names);
    }
}

class BootstrapBeforeEnv
{
    public function bootstrap($app) {
        $env_path = getenv('ENV_PATH'); // this needs to be `getenv` as framework has not started yet
        if (!empty($env_path)) {
            $app->useEnvironmentPath($env_path);
        }
    }
}

Hope that helps. (Sorry, if not - I've not looked at the specific config modification - and so could be completely orthogonal)

oppiansteve avatar Jan 17 '21 16:01 oppiansteve

@georgeboot upstream wasn't very open about making the real time facade cache path non-hardcoded to the storage path, I wouldn't get my hopes high on getting such PR accepted but I would love to be proved wrong.

yangm97 avatar Jan 22 '21 17:01 yangm97

Perhaps we could run artisan config:cache on the startup of the container? Don't believe the session token etc changes between invocations on the same container.

@georgeboot actually implemented that and that's live in the v2 of the new Laravel bridge 🙌

mnapoli avatar Mar 15 '23 09:03 mnapoli