Skip to content

Move Module Loading to Web Boot Stage and Keep start() Request-Only #504

Description

@armanist

Summary

Refactor the web app lifecycle so module loading and route collection building happen once during adapter boot, not on every request. Keep start() focused on per-request execution only.

Problem

WebAppAdapter::start() currently performs module loading (loadModules()) per request. In long-lived app instances (including feature tests with multiple requests), this causes repeated DI route registration behavior and lifecycle coupling between boot and request phases.

Goals

  1. Enforce lifecycle separation:
  • Boot phase: one-time app setup, including module/route loading.
  • Request phase: resolve route, run middleware/dispatch, send response, clean request-scoped state.
  1. Prevent repeated route collection registration across requests.
  2. Preserve backward-compatible request behavior (including downstream expectations around response() access after send).

Scope Requirements

  1. Add/restore LoadModulesStage under src/App/Stages/:
  • Register/get ModuleLoader.
  • Build RouteCollection via RouteBuilder from module route closures/config.
  • Store collection in DI.
  1. Wire LoadModulesStage into WebAppAdapter constructor boot pipeline.
  2. Remove per-request module-loading call from WebAppAdapter::start().
  3. Keep start() request-only flow:
  • OPTIONS handling
  • route resolution
  • dispatch/middleware flow
  • response send + request cleanup
  1. Keep request cleanup after send, but do not flush response payload in cleanup (compatibility requirement).

Non-Goals

  • No redesign of DI container semantics.
  • No reintroduction of handle() API unless separately scoped.
  • No dynamic hot-reload of modules/routes in normal runtime path.

Acceptance Criteria

  1. Core unit tests pass, including tests/Unit/App/Adapters/WebAppAdapterTest.php.
  2. Multiple requests against one app instance do not trigger route collection re-registration failures.
  3. Downstream feature suite passes without requiring app recreation per request.
  4. Request context is cleaned after send; response payload remains readable for compatibility.

Validation Plan

  1. Run core:
  • vendor/bin/phpunit
  • composer phpstan
  • composer cs:check
  1. Run downstream project full feature tests against path-linked core.
  2. Smoke test CLI/web startup manually.

Risks / Notes

  1. Runtime changes to module config/routes during the same app instance will no longer auto-apply per request.
  2. If dynamic refresh is needed later, add an explicit "reload routing/modules" mechanism as a separate ticket.

Deliverables

  1. Stage implementation file.
  2. Adapter pipeline update.
  3. Request-flow cleanup adjustments/tests.
  4. Changelog entry describing lifecycle contract.

Metadata

Metadata

Assignees

Labels

Type

Fields

No fields configured for Task.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions