Skip to content

Issue/589 Unify the app adapter lifecycle and let the pipeline own an early end of a run - #590

Merged
armanist merged 7 commits into
quantum-php:masterfrom
armanist:issue/589-adapter-lifecycle
Oct 21, 2026
Merged

armanist merged 7 commits into
quantum-php:masterfrom
armanist:issue/589-adapter-lifecycle

Conversation

@armanist

@armanist armanist commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #589

What changed

Why

Both adapters ran the same Pipeline, but each carried its own control flow. An early end of a web request was handled by hand in four stages, so a new stage could do work on an answered request if it forgot the check. The console boot caught any Throwable, kept it, carried it into the runtime and rethrew it from two places, treating a broken .env and a broken helper file the same way. Now the pipeline owns an early end, the context owns the state, and no adapter catches anything. It also gives every stage event of #538 one meaning: a stage that runs fires its events, a stage that does not run fires none.

Breaking changes

  • AppInterface gains boot(), and creating an adapter no longer boots it. Code that uses AppFactory is not affected; code that creates an adapter directly must call boot() before start().
  • ConsoleContext::getBootFailure() and its constructor argument are removed (both added earlier in 3.1.0).
  • RegisterCoreCommandsStage and RegisterAppCommandsStage moved from Quantum\App\Stages\Console to Quantum\App\Stages\Boot.
  • Compared with earlier 3.1.0 code: on a missing or malformed .env, an app command that does not require the environment no longer runs, and list shows only the core commands; a broken app helper file or an error handler that cannot be set up fails every command instead of being tolerated. Both match 3.0.3.

Testing

  • New tests:
    • PipelineTest: a stop ends the run and later stages dispatch no events; the closing stage runs with and without a stop, with its events, and not after a throw.
    • AppContextTest: the stop flag and the exit code.
    • WebAppAdapterTest, ConsoleAppAdapterTest: the constructor does not boot, boot() runs the boot stages; AppFactoryTest: the created app is booted.
    • ResolveEnvironmentStageTest: nothing happens on a valid .env; on a missing and on a malformed .env, the boot stops for a command that does not require the environment, list and help, and the exception reaches a command that requires the environment, an unknown command and no command.
    • CommandRegistrarTest: registering the core commands with only the helpers loaded loads neither the environment nor any config (fails before the three commands are changed).
    • ConsoleAppAdapterTest: every case of the behavior table of Unify the app adapter lifecycle and let the pipeline own an early end of a run #589, including an app command whose constructor reads env('APP_KEY').
  • The existing web adapter tests pass with no changed assertions; they only call boot() after creating the adapter. The removed tests covered the old boot failure and the per-stage isStopped() guards.
  • Checked on the starter project with this branch and with master, with identical results: GET / 200, GET /api/posts 200, OPTIONS /api/posts 204 with the CORS headers, a missing page 404 as HTML and as JSON; list, core:version and post:show on a valid .env; on a missing and on a malformed .env, list and core:env run and core:key, post:show, an unknown command and no command fail with the env exception.

Summary by CodeRabbit

  • New Features

    • Application startup is now explicitly completed before web or console execution.
    • Console commands can run without an environment when configured to do so.
    • Console startup now handles environment issues according to each command’s requirements.
    • Pipeline processing stops cleanly when requested while still completing its final stage.
  • Bug Fixes

    • Console boot errors are reported immediately instead of being deferred.
    • Web request processing continues consistently through response generation after a pipeline stop.
  • Documentation

    • Updated release documentation to describe the redesigned application boot and runtime behavior.

The stop flag and the exit code move to AppContext. A stage that stops
the context ends the run; the optional closing stage still runs, and the
web runtime uses it to send the response.
AppInterface gains boot(). The adapter constructors only store the
context, and AppFactory boots the adapter right after creating it.
The pipeline ends the run on a stop, so ResolveRouteStage,
HandleRouteNotFoundStage, PrepareRequestStage and DispatchRequestStage
no longer check isStopped() themselves.
DebugBarCommand, OpenApiCommand and ResourceCacheClearCommand get the
file system in exec() instead of in their constructor, so registering
the core commands loads no config. A test guards that registering them
needs neither the environment nor any config.
The console boot registers the core commands after the helpers and the
app commands at its end, after the environment, the config and the error
handler. The new ResolveEnvironmentStage lets core:env, list and help run
when the .env file is missing or malformed by stopping the boot; every
other command fails with the exception of the environment file.

The boot failure, both try/catch blocks of ConsoleAppAdapter and the boot
failure branch of RunCommandStage are removed.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-21T08:43:25.066758Z
We couldn’t complete this review. Comment @codex review to try again.
9a32bb4 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2bdaca49-9370-4af2-8351-fdd7fcf38e73
📥 Commits

Reviewing files that changed from the base of the PR and between 59199a3 and 9a32bb4.

📒 Files selected for processing: 43
  • CHANGELOG.md
  • src/App/Adapters/Console/ConsoleAppAdapter.php
  • src/App/Adapters/Console/ConsoleContext.php
  • src/App/Adapters/Web/WebAppAdapter.php
  • src/App/Adapters/Web/WebContext.php
  • src/App/AppContext.php
  • src/App/Contracts/AppInterface.php
  • src/App/Factories/AppFactory.php
  • src/App/Pipeline.php
  • src/App/Stages/Boot/InitConsoleStage.php
  • src/App/Stages/Boot/RegisterAppCommandsStage.php
  • src/App/Stages/Boot/RegisterCoreCommandsStage.php
  • src/App/Stages/Boot/ResolveEnvironmentStage.php
  • src/App/Stages/Console/RunCommandStage.php
  • src/App/Stages/Web/DispatchRequestStage.php
  • src/App/Stages/Web/HandleRouteNotFoundStage.php
  • src/App/Stages/Web/PrepareRequestStage.php
  • src/App/Stages/Web/ResolveRouteStage.php
  • src/App/Stages/Web/SendResponseStage.php
  • src/Console/Commands/DebugBarCommand.php
  • src/Console/Commands/OpenApiCommand.php
  • src/Console/Commands/ResourceCacheClearCommand.php
  • src/Environment/Environment.php
  • tests/Unit/App/Adapters/Console/ConsoleAppAdapterTest.php
  • tests/Unit/App/Adapters/Console/ConsoleContextTest.php
  • tests/Unit/App/Adapters/Web/WebAppAdapterTest.php
  • tests/Unit/App/AppContextTest.php
  • tests/Unit/App/AppTest.php
  • tests/Unit/App/Factories/AppFactoryTest.php
  • tests/Unit/App/PipelineTest.php
  • tests/Unit/App/Stages/Boot/RegisterAppCommandsStageTest.php
  • tests/Unit/App/Stages/Boot/RegisterCoreCommandsStageTest.php
  • tests/Unit/App/Stages/Boot/ResolveEnvironmentStageTest.php
  • tests/Unit/App/Stages/Console/ConsoleStageTestCase.php
  • tests/Unit/App/Stages/Console/RunCommandStageTest.php
  • tests/Unit/App/Stages/Web/DispatchRequestStageTest.php
  • tests/Unit/App/Stages/Web/HandleRouteNotFoundStageTest.php
  • tests/Unit/App/Stages/Web/PrepareRequestStageTest.php
  • tests/Unit/App/Stages/Web/ResolveRouteStageTest.php
  • tests/Unit/Console/CommandRegistrarTest.php
  • tests/Unit/Console/Commands/DebugBarCommandTest.php
  • tests/Unit/Console/Commands/OpenApiCommandTest.php
  • tests/Unit/Console/Commands/ResourceCacheClearCommandTest.php
💤 Files with no reviewable changes: 8
  • tests/Unit/App/Stages/Web/PrepareRequestStageTest.php
  • tests/Unit/App/Stages/Web/DispatchRequestStageTest.php
  • tests/Unit/App/Stages/Web/ResolveRouteStageTest.php
  • src/App/Stages/Web/PrepareRequestStage.php
  • tests/Unit/App/Stages/Web/HandleRouteNotFoundStageTest.php
  • src/App/Stages/Web/DispatchRequestStage.php
  • src/App/Stages/Web/ResolveRouteStage.php
  • tests/Unit/App/Adapters/Console/ConsoleContextTest.php

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Walkthrough

Adapters now boot explicitly, and AppContext owns pipeline stop and exit-code state. Pipelines stop later stages after a stop and can run a closing stage. Console boot resolves environment requirements before command execution. Web response sending runs as the closing stage.

Changes: Application lifecycle and runtime

Layer / File(s) Summary
Pipeline state and closing stage
src/App/AppContext.php, src/App/Pipeline.php, tests/Unit/App/AppContextTest.php, tests/Unit/App/PipelineTest.php
AppContext now stores stop state and an exit code. Pipeline skips later ordinary stages after a stop and runs its closing stage unless a stage throws.
Explicit adapter boot lifecycle
src/App/Contracts/AppInterface.php, src/App/Adapters/Console/*, src/App/Adapters/Web/*, src/App/Factories/AppFactory.php, tests/Unit/App/Adapters/*, tests/Unit/App/AppTest.php, tests/Unit/App/Factories/AppFactoryTest.php
Adapters expose boot() separately from construction. AppFactory boots its adapter before creating App. Console runtime contexts no longer store boot failures.
Console boot and environment resolution
src/App/Stages/Boot/*, src/App/Stages/Console/RunCommandStage.php, src/Environment/Environment.php, tests/Unit/App/Stages/Boot/*, tests/Unit/App/Stages/Console/*, tests/Unit/Console/CommandRegistrarTest.php, tests/Unit/App/Adapters/Console/ConsoleAppAdapterTest.php
Console boot registers core commands before resolving the environment, then registers application commands. Missing or malformed environment files stop boot for commands that do not require the environment; otherwise, the exception propagates.
Filesystem access in core commands
src/Console/Commands/DebugBarCommand.php, src/Console/Commands/OpenApiCommand.php, src/Console/Commands/ResourceCacheClearCommand.php, tests/Unit/Console/Commands/*
The three commands obtain FileSystem during execution and pass it to helper methods instead of storing it on the command.
Web runtime stop handling
src/App/Adapters/Web/*, src/App/Stages/Web/*, tests/Unit/App/Stages/Web/*
Web stages no longer check stopped state. SendResponseStage is configured to run as the closing stage.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant ConsoleAppAdapter
  participant Pipeline
  participant RegisterCoreCommandsStage
  participant ResolveEnvironmentStage
  participant Environment
  participant RegisterAppCommandsStage
  ConsoleAppAdapter->>Pipeline: Run boot stages
  Pipeline->>RegisterCoreCommandsStage: Register core commands
  Pipeline->>ResolveEnvironmentStage: Resolve environment
  ResolveEnvironmentStage->>Environment: Load environment
  Pipeline->>RegisterAppCommandsStage: Register application commands
Loading
Merge Risk: ⚪ Minimal · up to 9a32b

The console fallback remains able to run environment-independent commands. No actionable merge-blocking issue remains; merge after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 29.27% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 123 functions across 34 files. (1 skipped… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the two main changes: unified adapter lifecycle management and pipeline-owned early run termination.
Linked Issues check Passed The changes implement the coding requirements of [#589]. AppInterface defines boot(). Both adapters store context in the constructor, boot separate pipelines, and do not catch exceptions. `AppFact…
Out of Scope Changes check Passed The changes stay within [#589]. The adapter, pipeline, context, web-stage, console-boot, command-constructor, test, and changelog changes support the linked issue. Event assertions test the required p…
Full details: Linked Issues check

Explanation

The changes implement the coding requirements of [#589]. AppInterface defines boot(). Both adapters store context in the constructor, boot separate pipelines, and do not catch exceptions. AppFactory boots the created adapter. Pipeline stops later stages and their events, then runs the optional closing stage unless a stage throws. AppContext owns stop and exit-code state. The web runtime uses SendResponseStage as its closing stage and removes stage-level stop checks. Console boot registers core commands before environment resolution and app commands after configuration. ResolveEnvironmentStage catches only EnvException and InvalidFileException and applies the documented command behavior. The added tests cover lifecycle, pipeline, environment, command registration, and adapter behavior.

Full details: Out of Scope Changes check

Explanation

The changes stay within [#589]. The adapter, pipeline, context, web-stage, console-boot, command-constructor, test, and changelog changes support the linked issue. Event assertions test the required pipeline stop behavior; they do not add the runtime event feature identified as out of scope. No unrelated change is shown in the supplied change summary.

Full details: Docstring Coverage

Explanation

Docstring coverage is 29.27% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 123 functions across 34 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 86.36364% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/Console/Commands/OpenApiCommand.php 45.45% 6 Missing ⚠️
src/Console/Commands/ResourceCacheClearCommand.php 64.28% 5 Missing ⚠️
src/Console/Commands/DebugBarCommand.php 85.71% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@armanist
armanist merged commit 926909c into quantum-php:master Oct 21, 2026
6 checks passed
@armanist
armanist deleted the issue/589-adapter-lifecycle branch October 21, 2026 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unify the app adapter lifecycle and let the pipeline own an early end of a run

3 participants