refactor: unified kernal logic clean up

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-07-27 08:54:37 -04:00
parent 65c1b5fb75
commit eb99eb5a2e
10 changed files with 197 additions and 130 deletions
+2 -2
View File
@@ -70,9 +70,9 @@ final class Application
}
}
public function handleHttp(Request $request): Response
public function runHttpRequest(Request $request): Response
{
return $this->http->handle($request);
return $this->http->run($request, send: false);
}
public function runConsole(): int
@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace KTXC\Application\Execution;
use KTXC\KernelInterface;
final readonly class ExecutionRunner implements ExecutionRunnerInterface
{
public function __construct(
private KernelInterface $kernel,
) {
}
public function execute(
ExecutionDescriptor $descriptor,
callable $execution,
?callable $failure = null,
): mixed {
$scope = $this->kernel->beginExecution($descriptor);
$outcome = ExecutionOutcome::incomplete();
try {
$result = $execution($scope);
$outcome = ExecutionOutcome::success($result);
return $result;
} catch (\Throwable $error) {
if ($failure === null) {
$outcome = ExecutionOutcome::failure($error);
throw $error;
}
try {
$result = $failure($error, $scope);
$outcome = ExecutionOutcome::failure($error, $result);
return $result;
} catch (\Throwable $failureError) {
$outcome = ExecutionOutcome::failure($failureError);
throw $failureError;
}
} finally {
$this->kernel->terminateExecution($scope, $outcome);
}
}
}
@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace KTXC\Application\Execution;
interface ExecutionRunnerInterface
{
/**
* @template TResult
*
* @param callable(ExecutionScope): TResult $execution
* @param null|callable(\Throwable, ExecutionScope): TResult $failure
*
* @return TResult
*/
public function execute(
ExecutionDescriptor $descriptor,
callable $execution,
?callable $failure = null,
): mixed;
}
+23 -44
View File
@@ -12,6 +12,8 @@ namespace KTXC;
use KTXC\Application\KernelOptions;
use KTXC\Application\Execution\ExecutionDescriptor;
use KTXC\Application\Execution\ExecutionOutcome;
use KTXC\Application\Execution\ExecutionRunner;
use KTXC\Application\Execution\ExecutionRunnerInterface;
use KTXC\Application\Execution\ExecutionScope;
use KTXC\Application\Execution\TerminationReport;
use KTXC\Context\IdentityContext;
@@ -52,6 +54,7 @@ class Kernel implements KernelInterface
protected ?LoggerInterface $logger = null;
private bool $errorHandlerInstalled = false;
private ?ExecutionScope $activeScope = null;
private ?ExecutionRunnerInterface $runner = null;
private array $config;
@@ -67,6 +70,7 @@ class Kernel implements KernelInterface
$this->initialized = false;
$this->booted = false;
$this->container = null;
$this->runner = null;
}
private function initialize(): void
@@ -84,7 +88,10 @@ class Kernel implements KernelInterface
}
// Create logger from config (driver + level-filter; per-tenant wrapping applied later in DI)
$this->logger = LoggerFactory::create($this->config, $this->folderRoot());
$this->logger = LoggerFactory::create(
$this->config,
$this->options->paths->project,
);
$this->initializeErrorHandlers();
@@ -162,6 +169,11 @@ class Kernel implements KernelInterface
}
}
public function executionRunner(): ExecutionRunnerInterface
{
return $this->runner ??= new ExecutionRunner($this);
}
public function reboot(): void
{
$this->shutdown();
@@ -284,8 +296,12 @@ class Kernel implements KernelInterface
*/
protected function parameters(): array
{
$projectDir = $this->options->paths->project;
$cacheDir = $this->options->paths->cache($this->environment());
$logsDir = $this->options->paths->logs();
return [
'kernel.project_dir' => realpath($this->folderRoot()) ?: $this->folderRoot(),
'kernel.project_dir' => realpath($projectDir) ?: $projectDir,
'kernel.environment' => $this->environment(),
'kernel.runtime_environment' => '%env(default:kernel.environment:APP_RUNTIME_ENV)%',
'kernel.runtime_mode' => '%env(query_string:default:container.runtime_mode:APP_RUNTIME_MODE)%',
@@ -293,10 +309,10 @@ class Kernel implements KernelInterface
'kernel.runtime_mode.cli' => '%env(not:default:kernel.runtime_mode.web:)%',
'kernel.runtime_mode.worker' => '%env(bool:default::key:worker:default:kernel.runtime_mode:)%',
'kernel.debug' => $this->debug(),
'kernel.build_dir' => realpath($this->getBuildDir()) ?: $this->getBuildDir(),
'kernel.cache_dir' => realpath($this->getCacheDir()) ?: $this->getCacheDir(),
'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(),
'kernel.charset' => $this->getCharset(),
'kernel.build_dir' => realpath($cacheDir) ?: $cacheDir,
'kernel.cache_dir' => realpath($cacheDir) ?: $cacheDir,
'kernel.logs_dir' => realpath($logsDir) ?: $logsDir,
'kernel.charset' => 'UTF-8',
];
}
@@ -324,43 +340,6 @@ class Kernel implements KernelInterface
return $this->debug() && null !== $this->startTime ? $this->startTime : -\INF;
}
/**
* Gets the application root dir (path of the project's composer file).
*/
public function folderRoot(): string
{
return $this->options->paths->project;
}
/**
* Gets the path to the configuration directory.
*/
private function getConfigDir(): string
{
return $this->options->paths->configuration();
}
public function getCacheDir(): string
{
return $this->options->paths->cache($this->environment());
}
public function getBuildDir(): string
{
return $this->getCacheDir();
}
public function getLogDir(): string
{
return $this->options->paths->logs();
}
public function getCharset(): string
{
return 'UTF-8';
}
/**
* Initializes the service container
*/
@@ -393,7 +372,7 @@ class Kernel implements KernelInterface
protected function configureContainer(Builder $builder): void
{
// Service definitions
$projectDir = $this->folderRoot();
$projectDir = $this->options->paths->project;
$moduleDir = $projectDir . '/modules';
$environment = $this->environment();
+3
View File
@@ -6,6 +6,7 @@ namespace KTXC;
use KTXC\Application\Execution\ExecutionDescriptor;
use KTXC\Application\Execution\ExecutionOutcome;
use KTXC\Application\Execution\ExecutionRunnerInterface;
use KTXC\Application\Execution\ExecutionScope;
use KTXC\Application\Execution\TerminationReport;
use Psr\Container\ContainerInterface;
@@ -14,6 +15,8 @@ interface KernelInterface
{
public function boot(): void;
public function executionRunner(): ExecutionRunnerInterface;
public function beginExecution(ExecutionDescriptor $descriptor): ExecutionScope;
public function terminateExecution(
+21 -42
View File
@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace KTXC\Runtime\Console;
use KTXC\Application\Execution\ExecutionDescriptor;
use KTXC\Application\Execution\ExecutionOutcome;
use KTXC\Kernel;
use KTXC\KernelInterface;
use KTXC\Module\ModuleManager;
@@ -24,57 +23,37 @@ final class ConsoleRuntime
) {
}
public function run(
?InputInterface $input = null,
?OutputInterface $output = null,
): int
public function run(?InputInterface $input = null, ?OutputInterface $output = null): int
{
$scope = $this->kernel->beginExecution(ExecutionDescriptor::cli());
$outcome = ExecutionOutcome::incomplete();
return $this->kernel->executionRunner()->execute(
ExecutionDescriptor::cli(),
function () use ($input, $output): int {
$container = $this->kernel->container();
$console = new ConsoleApplication('Vallarx Console', Kernel::VERSION);
$console->setAutoExit(false);
try {
$exitCode = $this->application()->run($input, $output);
$outcome = ExecutionOutcome::success($exitCode);
/** @var ModuleManager $moduleManager */
$moduleManager = $container->get(ModuleManager::class);
foreach ($moduleManager->list() as $module) {
$instance = $module->instance();
if (!$instance instanceof ModuleConsoleInterface) {
continue;
}
return $exitCode;
} catch (\Throwable $error) {
$outcome = ExecutionOutcome::failure($error);
throw $error;
} finally {
$this->kernel->terminateExecution($scope, $outcome);
}
}
foreach ($instance->registerCI() as $commandClass) {
$this->registerCommand($console, $container, $commandClass);
}
}
private function application(): ConsoleApplication
{
$container = $this->kernel->container();
$console = new ConsoleApplication('Vallarx Console', Kernel::VERSION);
$console->setAutoExit(false);
/** @var ModuleManager $moduleManager */
$moduleManager = $container->get(ModuleManager::class);
foreach ($moduleManager->list() as $module) {
$instance = $module->instance();
if (!$instance instanceof ModuleConsoleInterface) {
continue;
return $console->run($input, $output);
}
foreach ($instance->registerCI() as $commandClass) {
$this->registerLazyCommand($console, $container, $commandClass);
}
}
return $console;
);
}
/**
* @param class-string $commandClass
*/
private function registerLazyCommand(
ConsoleApplication $console,
ContainerInterface $container,
string $commandClass,
): void {
private function registerCommand(ConsoleApplication $console, ContainerInterface $container, string $commandClass): void {
if (!class_exists($commandClass)) {
throw new \RuntimeException("Command class not found: {$commandClass}");
}
+21 -39
View File
@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace KTXC\Runtime\Http;
use KTXC\Application\Execution\ExecutionDescriptor;
use KTXC\Application\Execution\ExecutionOutcome;
use KTXC\Http\Middleware\AuthenticationMiddleware;
use KTXC\Http\Middleware\FirewallMiddleware;
use KTXC\Http\Middleware\MiddlewarePipeline;
@@ -23,48 +22,31 @@ final class HttpRuntime
) {
}
public function run(?Request $request = null): Response
public function run(?Request $request = null, bool $send = true): Response
{
return $this->execute(
$request ?? Request::createFromGlobals(),
send: true,
$request ??= Request::createFromGlobals();
return $this->kernel->executionRunner()->execute(
ExecutionDescriptor::http(),
function () use ($request, $send): Response {
$response = $this->pipeline()->handle($request);
if ($send) {
$response->send();
}
return $response;
},
function (\Throwable $error) use ($send): Response {
$response = $this->errorResponse($error);
if ($send) {
$response->send();
}
return $response;
},
);
}
public function handle(Request $request): Response
{
return $this->execute($request, send: false);
}
private function execute(Request $request, bool $send): Response
{
$scope = null;
$outcome = ExecutionOutcome::incomplete();
try {
$scope = $this->kernel->beginExecution(ExecutionDescriptor::http());
$response = $this->pipeline()->handle($request);
$outcome = ExecutionOutcome::success($response);
if ($send) {
$response->send();
}
return $response;
} catch (\Throwable $error) {
$response = $this->errorResponse($error);
$outcome = ExecutionOutcome::failure($error, $response);
if ($send) {
$response->send();
}
return $response;
} finally {
if ($scope !== null) {
$this->kernel->terminateExecution($scope, $outcome);
}
}
}
private function pipeline(): MiddlewarePipeline
{
$pipeline = new MiddlewarePipeline($this->kernel->container());