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

[spiral/boot] Added the ability to configure bootloaders via BootloadConfig #1017

Merged
merged 2 commits into from
Nov 23, 2023

Conversation

msmakouz
Copy link
Member

@msmakouz msmakouz commented Nov 23, 2023

Spiral continues to evolve, offering more flexibility and efficiency in its latest update. Developers now have enhanced control over the configuration of bootloaders. This update is particularly beneficial for tailoring applications to different environments, such as HTTP, CLI, or gRPC, by enabling or disabling specific bootloaders as needed. It allows for a more nuanced and environment-specific configuration of bootloaders. This feature is particularly useful in scenarios where certain bootloaders are only relevant in specific contexts. For instance, in an HTTP environment, bootloaders like HTTPBootloader and RoutesBootloader are essential, whereas they might be unnecessary in CLI or gRPC environments. By enabling the selective enabling or disabling of bootloaders, it helps in optimizing resource usage and improving application performance.

BootloadConfig

There is a new DTO class Spiral\Boot\Attribute\BootloadConfig which enables the inclusion or exclusion of bootloaders, passing parameters that will be forwarded to the init and boot methods of the bootloader, and dynamically adjusting the bootloader loading based on environment variables. It can be used within the Kernel as a value in the array of bootloaders. Alternatively, it can be used as an attribute that needs to be added to the bootloader class.

The BootloadConfig class constructor accepts the following parameters:

  • args: An array of arguments that will be passed to the init and boot methods of the bootloader.
  • enabled: Specifies whether to load the bootloader or not. It has a default value of true.
  • allowEnv: An array where you can define the values of environment variables that permit the bootloader to be loaded. All specified environment variables must be defined and have the required value or one of the specified values (if an array of values is provided).
  • denyEnv: An array where you can specify with which environment variables the bootloader should not be loaded. The bootloader will not be loaded if any of the specified environment variables have the specified value.
  • override: Indicates whether to override attribute values or not. If an attribute is set on the bootloader, configuring it in the Kernel allows you to override the values specified in the attribute. The default is true. If set to false, the arrays of args, allowEnv, and denyEnv will be merged and overridden only when the keys match. The enabled parameter is always overridden.

Usage in Kernel

To use it in the Kernel, you should employ the full class name of the bootloader as the key in the array of bootloaders, with the corresponding value being a Spiral\Boot\Attribute\BootloadConfig object.

namespace App\Application;

use Spiral\Boot\Attribute\BootloadConfig;
use Spiral\Prototype\Bootloader\PrototypeBootloader;

class Kernel extends \Spiral\Framework\Kernel
{
    // ...
    public function defineBootloaders(): array
    {
        return [
            // ...
            PrototypeBootloader::class => new BootloadConfig(allowEnv: ['APP_ENV' => ['local', 'dev']]),
            // ...
        ];
    }
    
    // ...
}

In this example, we specified that the PrototypeBootloader should be loaded only if the environment variable APP_ENV is defined and has a value of local or dev.

Instead of creating a BootloadConfig object directly, you can define a function that returns a BootloadConfig object. This function can take arguments, which might be obtained from the container.

namespace App\Application;

use Spiral\Boot\Attribute\BootloadConfig;
use Spiral\Boot\Environment\AppEnvironment;
use Spiral\Prototype\Bootloader\PrototypeBootloader;

class Kernel extends \Spiral\Framework\Kernel
{
    // ...
    public function defineBootloaders(): array
    {
        return [
            // ...
            PrototypeBootloader::class => fn (AppEnvironment $env) => new BootloadConfig(enabled: $env->isLocal()),
            // ...
        ];
    }

    // ...
}

Using Attributes for Bootloader Configuration

You can also use Spiral\Boot\Attribute\BootloadConfig class as an attribute to control how a bootloader behaves. This method is particularly useful because it allows you to set up the configuration directly in the bootloader's class, making it more straightforward and easier to understand.

Here's a simple example of how you can use an attribute to configure a bootloader:

use Spiral\Boot\Attribute\BootloadConfig;
use Spiral\Boot\Bootloader\Bootloader;

#[BootloadConfig(allowEnv: ['APP_ENV' => 'local'])]
final class SomeBootloader extends Bootloader
{
}

Attributes are a great choice when you want to keep the configuration close to the bootloader's code. It's a more intuitive way to set up bootloaders, especially in cases where the configuration is straightforward and doesn't require complex logic. By using attributes, you can easily see and understand the conditions under which a particular bootloader will be active, all in one place.

Extending for Custom Preconditions

By extending BootloadConfig, you can create custom classes that encapsulate specific conditions under which bootloaders should operate. This approach simplifies the usage of bootloaders by abstracting the configuration details into these custom classes.

Here's an example

class TargetRRWorker extends BootloadConfig {
    public function __construct(array $modes)
    {
        parent::__construct(
            env: ['RR_MODE' => $modes],
        );
    }
}

Now you can use it in your bootloaders

use Spiral\Boot\Bootloader\Bootloader;

#[TargetRRWorker(['http'])]
final class HttpBootloader extends Bootloader
{
    // Bootloader code goes here
}

or use in Kernel:

namespace App\Application;

use Spiral\Framework\Kernel;

class Kernel extends Kernel
{
    public function defineBootloaders(): array
    {
        return [
            HttpBootloader::class => new TargetRRWorker(['http']),
            RoutesBootloader::class => new TargetRRWorker(['http']),
            // Other bootloaders...
        ];
    }
}

The ability to extend BootloadConfig opens up a world of possibilities for customizing the behavior of bootloaders.

@msmakouz msmakouz added this to the 3.10 milestone Nov 23, 2023
@msmakouz msmakouz requested a review from butschster November 23, 2023 13:39
@msmakouz msmakouz self-assigned this Nov 23, 2023
Copy link

codecov bot commented Nov 23, 2023

Codecov Report

Attention: 1 lines in your changes are missing coverage. Please review.

Comparison is base (c618ac7) 89.19% compared to head (2d2886f) 89.23%.
Report is 5 commits behind head on master.

Files Patch % Lines
src/Boot/src/BootloadManager/Initializer.php 97.82% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #1017      +/-   ##
============================================
+ Coverage     89.19%   89.23%   +0.03%     
- Complexity     6138     6188      +50     
============================================
  Files           809      816       +7     
  Lines         17338    17447     +109     
============================================
+ Hits          15464    15568     +104     
- Misses         1874     1879       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@msmakouz msmakouz changed the title [spiral/boot] Added the ability to configure bootloaders via BootloaderRules [spiral/boot] Added the ability to configure bootloaders via BootloadConfig Nov 23, 2023
@butschster butschster merged commit 441f912 into master Nov 23, 2023
8 of 9 checks passed
@butschster butschster deleted the feature/bootloader-rules branch November 23, 2023 21:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

2 participants