Skip to content

refactor(core): refactor lambda application and builder#163

Merged
j-d-ha merged 164 commits into
mainfrom
feature/#99-refactor-lambda-application-and-interfaces
Nov 23, 2025
Merged

refactor(core): refactor lambda application and builder#163
j-d-ha merged 164 commits into
mainfrom
feature/#99-refactor-lambda-application-and-interfaces

Conversation

@j-d-ha

@j-d-ha j-d-ha commented Nov 23, 2025

Copy link
Copy Markdown
Collaborator

Summary

This PR represents a major architectural refactoring of the aws-lambda-host framework, replacing the monolithic ILambdaApplication interface with specialized builder interfaces (ILambdaInvocationBuilder, ILambdaOnInitBuilder, ILambdaOnShutdownBuilder) that provide clearer separation of concerns. The refactoring includes comprehensive unit tests, improved feature collection architecture, and enhanced lifecycle management.

Key improvements:

  • Clearer API surface with three specialized builder interfaces instead of a single monolithic interface
  • Comprehensive unit test coverage across all builder, context, and feature classes
  • Enhanced feature collection system for accessing invocation-scoped and shared data
  • Improved lifecycle management with dedicated initialization and shutdown builders
  • Simplified namespace structure and better internal organization
  • Complete documentation updates reflecting the new architecture

Test Coverage: 67 new unit test classes with 2,000+ test cases added, covering:

  • Builder factories and composition
  • Context and service management
  • Feature collection and access patterns
  • Lifecycle handlers and orchestration
  • Middleware and extension integration

Breaking Changes

1. ILambdaApplication Removed (BREAKING)

Removed in: refactor(abstractions): remove ILambdaApplication and update namespaces

The ILambdaApplication interface has been removed from AwsLambda.Host.Abstractions. This interface was the previous monolithic API for all Lambda configuration.

Migration:
Replace ILambdaApplication references with the appropriate specialized builder interface:

  • For handler registration → ILambdaInvocationBuilder
  • For initialization handlers → ILambdaOnInitBuilder
  • For shutdown handlers → ILambdaOnShutdownBuilder

Before:

var app = LambdaApplication.CreateBuilder()
    .ConfigureServices(services => { /* ... */ })
    .Build();

// Single interface for all operations
app.Handle(handler);
app.OnInit(initHandler);
app.OnShutdown(shutdownHandler);

After:

var app = LambdaApplication.CreateBuilder()
    .ConfigureServices(services => { /* ... */ })
    .Build();

// Specialized interfaces for each concern
var invocationBuilder = (ILambdaInvocationBuilder)app;
var initBuilder = (ILambdaOnInitBuilder)app;
var shutdownBuilder = (ILambdaOnShutdownBuilder)app;

invocationBuilder.Handle(handler);
initBuilder.OnInit(initHandler);
shutdownBuilder.OnShutdown(shutdownHandler);

2. Namespace Reorganization (BREAKING)

Affected in: Multiple commits organizing features and builder types into logical namespaces

Core types have been reorganized into dedicated namespaces:

Old Namespace New Namespace
AwsLambda.Host.* AwsLambda.Host.Builder.*
AwsLambda.Host.* AwsLambda.Host.Core.Features.*
AwsLambda.Host.* AwsLambda.Host.Core.Context.*
AwsLambda.Host.* AwsLambda.Host.Core.Options.*
AwsLambda.Host.* AwsLambda.Host.Core.Runtime.*

Global Usings have been added to simplify imports:

  • AwsLambda.Host.Abstractions in AwsLambda.Host.Abstractions/GlobalUsings.cs
  • AwsLambda.Host.Builder, AwsLambda.Host.Core.* in AwsLambda.Host/GlobalUsings.cs

3. ILambdaCancellationFactory Moved to Core (BREAKING)

Moved in: refactor(core): rename IOnInitBuilderFactorytoILambdaOnInitBuilderFactory``

Moved from AwsLambda.Host.AbstractionsAwsLambda.Host.Abstractions.Core

Update imports:

// Before
using AwsLambda.Host.Abstractions;

// After
using AwsLambda.Host.Abstractions.Core;

4. Handler Delegate Signatures Unchanged

Handler delegates remain compatible:

  • LambdaInvocationDelegate(ILambdaHostContext context) : Task
  • LambdaInitDelegate(IServiceProvider, CancellationToken) : Task<bool>
  • LambdaShutdownDelegate(IServiceProvider, CancellationToken) : Task

5. Builder Factory Interface Renames (BREAKING)

Renamed in: refactor(core): rename interface names for consistency

Factory interfaces now follow a consistent naming pattern:

Old Name New Name
IInvocationBuilderFactory ILambdaInvocationBuilderFactory
IOnInitBuilderFactory ILambdaOnInitBuilderFactory
IOnShutdownBuilderFactory ILambdaOnShutdownBuilderFactory

These are internal interfaces but if you have custom implementations, update references accordingly.

6. Feature Collection Architecture (BREAKING)

Added in: feat(host): implement feature collection factory pattern

The feature collection system has been redesigned:

  • IFeatureCollection now requires feature providers
  • IEventFeature<T> and IResponseFeature<T> provide strongly-typed access
  • Feature providers are registered through IFeatureProvider

Before:

// Limited feature support
var context = await GetContext();

After:

// Rich feature access through feature collection
var context = await GetContext();
var eventFeature = context.Features.Get<IEventFeature<MyEvent>>();
var responseFeature = context.Features.Get<IResponseFeature<MyResponse>>();

// Or use convenience methods
var @event = context.GetRequiredEvent<MyEvent>();
var response = context.GetRequiredResponse<MyResponse>();

7. Context Extension Methods Updated (BREAKING)

Changed in: feat(core): add GetRequiredEvent<T> and GetRequiredResponse<T> to Lambda context extensions

New convenience methods added to ILambdaHostContext:

  • GetRequiredEvent<T>() – Get strongly-typed event data
  • GetRequiredResponse<T>() – Get strongly-typed response data

These are extensions, so existing context.Items and context.Properties access remain unchanged.

8. OpenTelemetry Namespace Updates (BREAKING)

Changed in: refactor(core): update namespaces in OpenTelemetry extensions

OpenTelemetry extensions now in dedicated namespace:

// Before
using AwsLambda.Host.OpenTelemetry;

// After
using AwsLambda.Host.OpenTelemetry.Extensions;

9. Removed Obsolete Types (BREAKING)

  • ILambdaLifecycleOrchestrator – Removed; functionality replaced by builder factories
  • LambdaLifecycleOrchestrator – Removed; internal implementation detail
  • LambdaApplication (old class) – Replaced with new builder-focused implementation

Changes Summary

Builder Architecture

  • ✅ Added ILambdaInvocationBuilder for handler and middleware configuration
  • ✅ Added ILambdaOnInitBuilder for initialization handler management
  • ✅ Added ILambdaOnShutdownBuilder for shutdown handler management
  • ✅ Added dedicated factory implementations for each builder type
  • ✅ Refactored LambdaApplication to implement all three builder interfaces

Feature Collection System

  • ✅ Implemented IFeatureCollection and DefaultFeatureCollection
  • ✅ Added IFeatureProvider for pluggable feature management
  • ✅ Created DefaultEventFeature<T> and DefaultResponseFeature<T> for strongly-typed data access
  • ✅ Added factory pattern with IFeatureCollectionFactory

Context and Lifecycle

  • ✅ Enhanced ILambdaHostContext with feature access
  • ✅ Added convenience methods GetRequiredEvent<T>() and GetRequiredResponse<T>()
  • ✅ Improved DefaultLambdaHostContext implementation
  • ✅ Enhanced cancellation handling with DefaultLambdaCancellationFactory

Service Integration

  • ✅ Added ServiceCollectionExtensions for fluent service registration
  • ✅ Added HostOptionsPostConfiguration for options binding
  • ✅ Improved DI integration across builder phases

Code Organization

  • ✅ Moved builder types to AwsLambda.Host.Builder namespace
  • ✅ Moved context/features to AwsLambda.Host.Core namespace
  • ✅ Organized tests into logical folder structure
  • ✅ Added global usings for cleaner imports

Test Coverage

  • ✅ 67 new unit test classes
  • ✅ Comprehensive builder factory tests
  • ✅ Context and feature collection tests
  • ✅ Lifecycle handler tests
  • ✅ Extension method tests
  • ✅ Middleware and service integration tests
  • ✅ Runtime and bootstrap tests

Documentation

  • ✅ Updated CLAUDE.md with testing guidelines
  • ✅ Updated abstractions README with new architecture
  • ✅ Updated host README with builder API details
  • ✅ Enhanced envelope and OpenTelemetry documentation
  • ✅ Added XML documentation for public APIs

Checklist

  • My changes build cleanly
  • I've added/updated relevant tests (67 new unit test classes)
  • I've added/updated documentation or README
  • I've followed the coding style for this project
  • I've tested the changes locally

Related Issues

Closes #99


Migration Guide

For a complete migration guide from the old API to the new builder-based architecture, see:


Notes for Reviewers

Key areas to review:

  1. Builder Pattern Implementation – Verify the three builder interfaces provide clear separation of concerns
  2. Feature Collection System – Review the feature provider architecture and access patterns
  3. Test Coverage – Examine the new unit tests, especially around lifecycle and context management
  4. Namespace Organization – Confirm the new structure is logical and follows conventions
  5. Backward Compatibility – Note this is a major refactoring with breaking changes documented above
  6. Documentation – Ensure READMEs accurately reflect the new APIs and migration path

Known considerations:

  • This refactoring removes the monolithic ILambdaApplication in favor of specialized builder interfaces
  • All three packages are versioned together, so this will be a major version bump
  • Example projects have been updated to demonstrate the new API patterns
  • Source generators have been updated to work with the new builder factories

- Introduced `IFeatureCollection` for feature management in lambda handlers.
- Added `ILambdaHandlerBuilder` to configure handler pipelines and features.
- Implemented `ILambdaOnShutdownBuilder` for shutdown event handling.
- Added `ILambdaOnInitBuilder` for initialization event handling.
…ensing

- Added `FeatureCollection` implementation for feature management in AWS Lambda hosting.
- Updated `IFeatureCollection` with additional methods for feature access and setting.
- Included `THIRD-PARTY-LICENSES.txt` referencing azure-functions-dotnet-worker under MIT License.
- Introduced `LambdaHostedServiceOptions` to manage lambda lifecycle configuration.
- Added properties for `ConfigureHandlerBuilder`, `ConfigureOnInitBuilder`, and `ConfigureOnShutdownBuilder`.
- Updated solution with `THIRD-PARTY-LICENSES.txt` inclusion.
…terfaces

- Updated method signatures to use `ILambdaHandlerBuilder`, `ILambdaOnInitBuilder`, and `ILambdaOnShutdownBuilder`.
- Adjusted related return types and parameters in extensions for consistency with the builder pattern.
- Replaced application shutdown registration with direct addition to `ShutdownHandlers`.
- Enhanced clarity and alignment with builder pattern refinements.
- Updated `ILambdaHandlerBuilderFactory`, `ILambdaOnInitBuilderFactory`, and `ILambdaOnShutdownBuilderFactory`
  to be internal for improved encapsulation.
- Ensured compatibility with builder pattern refinements and previous lifecycle management updates.
- Added `[Obsolete]` attribute to `ILambdaApplication` with a deprecation message.
- Indicates intent to remove the interface in future updates.
…uilder`

- Renamed `ILambdaHandlerBuilder` and related classes to `ILambdaInvocationBuilder` for clarity.
- Updated method signatures, properties, and factory methods across host and pipeline.
- Ensured consistent naming in extensions, middleware, and hosted service options.
…ce access

- Added support for default OnInit handlers when `ClearLambdaOutputFormatting` is enabled.
- Introduced properties for accessing core services like `Configuration`, `Environment`, `Lifetime`, and `Logger`.
- Ensured fallback to `NullLogger` when no logger factory is available.
…tionBuilderFactory`

- Updated class and interface naming for improved clarity and consistency.
- Adjusted related references in the codebase accordingly.
…ambdaApplication`

- Added support for `ILambdaInvocationBuilder`, `ILambdaOnInitBuilder`, and `ILambdaOnShutdownBuilder` in `LambdaApplication`.
- Updated related properties, methods, and lifecycle management to use builder pattern.
- Registered core builder factories in the service collection.
…older

Move builder interfaces to a dedicated Builders subfolder for better organization
and discoverability of related builder types.
…ename LambdaStartupDelegate

- Move LambdaInvocationDelegate, LambdaShutdownDelegate to Delegates/ subfolder
- Rename LambdaStartupDelegate to LambdaInitDelegate for semantic alignment with Init lifecycle phase
- Update source generators to reference new delegate names and locations
… folder

Move IRequestEnvelope and IResponseEnvelope to a dedicated Envelopes subfolder
for better organization of envelope-related types.
- Move IFeatureCollection to Features subfolder
- Add new feature interfaces: IEventFeature, IFeatureProvider, IResponseFeature
- Enhance ILambdaHostContext with feature collection support
Rename implementation classes with Default prefix to follow convention:
- LambdaXxxBuilderFactory → DefaultXxxBuilderFactory (3 factories)
- LambdaCancellationTokenSourceFactory → DefaultLambdaCancellationFactory
- LambdaHostContext → DefaultLambdaHostContext
- FeatureCollection → DefaultFeatureCollection
- FeatureCollectionFactory → DefaultFeatureCollectionFactory

This signals these are standard implementations, leaving room for alternatives.
Remove 'Lambda' prefix from internal factory interfaces for reduced verbosity:
- ILambdaInvocationBuilderFactory → IInvocationBuilderFactory
- ILambdaOnInitBuilderFactory → IOnInitBuilderFactory
- ILambdaOnShutdownBuilderFactory → IOnShutdownBuilderFactory
- ILambdaCancellationTokenSourceFactory → ILambdaCancellationFactory

Update implementations and service registrations to use new names.
…and extensions

- Update FeatureCollectionExtensions with new factory references
- Extract LambdaHostContextExtensions to FeatureLambdaHostContextExtensions for better co-location
- Remove old factory and extension files (consolidated into new structure)
…ndling

Introduce RawInvocationData to encapsulate raw event and response streams
for low-level invocation handling scenarios.
Update LambdaApplication to implement builder interfaces and use new factory
interface names for invocation, init, and shutdown builders.
Update LambdaHandlerComposer to use simplified factory interface names
and update related hosted service tests.
Update source generators to use new delegate names and add support for
LambdaApplicationBuilder.Build() syntax generation.
Update OpenTelemetry integration to use new delegate names (LambdaInitDelegate)
and simplified factory interface names. Update related unit tests.
Rename test file for DefaultLambdaCancellationFactory and update verify
test snapshots for new delegate names.
Remove old file paths that have been moved/renamed as part of the
refactoring of builder interfaces, delegates, envelopes, and factory
implementations.
…pattern

- Replace direct TimeSpan usage with Options pattern for LambdaHostOptions.
- Update all test methods to initialize DefaultLambdaCancellationFactory with Options.Create.
- Ensure test assertions remain consistent with updated initialization logic.
…orts

- Replaced `Stream`-based handler with direct `Request` and `Response` objects for clarity.
- Removed unused imports: `System.IO` and `System.Text.Json` for cleaner and more maintainable code.
- Updated middleware logging messages for consistent format.
…ancements

- Add examples for `UseMiddleware()` with updated context parameters (`next(context)`).
- Introduce new usage examples of `OnInit()` and `OnShutdown()` with dependency injection.
- Document new configuration options: `ShutdownDuration`, `ShutdownDurationBuffer`, and
  `ClearLambdaOutputFormatting`.
- Enhance examples to reflect improved middleware handling patterns and updated APIs.
- Updated method signatures and extended descriptions for `Handle()`, `Use()`, and builder properties.
- Added new sections for `ILambdaHostContext`, highlighting contextual features and extended options.
- Clarified differences between `Properties` and `Items` for build-time vs invocation-scoped data.
- Improved documentation on the lifecycle: initialization (`OnInit`) and shutdown (`OnShutdown`).
- Corrected and streamlined code examples for setting up OpenTelemetry with AWS Lambda.
- Updated namespace usage to reflect current builder API (`AwsLambda.Host.Builder`).
- Simplified resource builder and handler mapping examples for clarity and accuracy.
- Replaced outdated `AddSource` configuration with a more concise `MapHandler` usage example.
…r examples

- Updated SQS handler example to include batch response handling for errors in message processing.
- Streamlined code to use `SQSBatchResponse` for unprocessed SQS messages.
- Improved API Gateway example to align with modern builder patterns and naming conventions.
- Added clarity on internal record types and updated example formatting for readability.
- Adjusted example code to use `AwsLambda.Host.Builder` namespace for consistency.
- Improved clarity in example setup for dependency injection.
…tation

- Updated README files across multiple components to ensure consistent line break formatting.
- Applied improved readability for long method descriptions and builder flow diagrams.
- Reformatted parameters and remarks sections in XML documentation for clarity.
- Simplified inconsistent spacing in sample and inline code examples.
@github-actions github-actions Bot added breaking-change Introduces a breaking change type: refactor Code refactoring labels Nov 23, 2025
@codecov

codecov Bot commented Nov 23, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.73684% with 33 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...SyntaxProviders/Extractors/HandlerInfoExtractor.cs 80.00% 3 Missing and 7 partials ⚠️
...st/Builder/Middleware/RequestEnvelopeMiddleware.cs 23.07% 10 Missing ⚠️
...c/AwsLambda.Host/Runtime/LambdaBootstrapAdapter.cs 0.00% 4 Missing ⚠️
...ers/LambdaApplicationBuilderBuildSyntaxProvider.cs 93.93% 1 Missing and 1 partial ⚠️
...bda.Host/Core/Features/DefaultFeatureCollection.cs 88.88% 1 Missing and 1 partial ⚠️
...rc/AwsLambda.Host/Runtime/LambdaHandlerComposer.cs 94.73% 1 Missing and 1 partial ⚠️
...a.Host.SourceGenerators/Models/SimpleMethodInfo.cs 0.00% 1 Missing ⚠️
src/AwsLambda.Host/Builder/LambdaApplication.cs 97.50% 0 Missing and 1 partial ⚠️
src/AwsLambda.Host/Runtime/LambdaHostedService.cs 96.55% 0 Missing and 1 partial ⚠️

Impacted file tree graph

@@             Coverage Diff             @@
##             main     #163       +/-   ##
===========================================
+ Coverage   80.26%   90.70%   +10.43%     
===========================================
  Files          60       74       +14     
  Lines        1728     1990      +262     
  Branches      202      226       +24     
===========================================
+ Hits         1387     1805      +418     
+ Misses        254       95      -159     
- Partials       87       90        +3     
Files with missing lines Coverage Δ
...Lambda.Host.Abstractions/Core/RawInvocationData.cs 100.00% <100.00%> (ø)
...ambda.Host.Abstractions/Options/EnvelopeOptions.cs 100.00% <ø> (ø)
....Host.OpenTelemetry/LambdaOpenTelemetryAdapters.cs 100.00% <100.00%> (ø)
...OpenTelemetry/OnShutdownOpenTelemetryExtensions.cs 100.00% <100.00%> (ø)
...SourceGenerators/MapHandlerIncrementalGenerator.cs 95.83% <100.00%> (-4.17%) ⬇️
...da.Host.SourceGenerators/Models/CompilationInfo.cs 100.00% <100.00%> (ø)
...ambda.Host.SourceGenerators/Models/DelegateInfo.cs 93.75% <100.00%> (ø)
...nerators/OutputGenerators/GenericHandlerSources.cs 98.01% <100.00%> (+0.01%) ⬆️
...tors/OutputGenerators/LambdaHostOutputGenerator.cs 100.00% <100.00%> (ø)
...ceGenerators/OutputGenerators/MapHandlerSources.cs 97.29% <100.00%> (+0.23%) ⬆️
... and 44 more

... and 2 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 44f989d...cfe5f90. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

j-d-ha and others added 16 commits November 22, 2025 20:26
- Adjusted line breaks in XML documentation for tracing middleware description.
- Reformatted ILoggerFactory configuration details for improved clarity.
…up mocks

- Introduced `AutoNSubstituteDataAttribute` for automating mock setup in unit tests.
- Replaced manual mock creation and initialization with `[AutoNSubstituteData]`.
- Simplified test code by removing redundant `CreateMocks` utility and inline mocks setup.
- Updated tests to use `Theory` instead of `Fact` for parameterized test cases.
- Added new `AutoNSubstituteDataAttribute` and `InlineAutoNSubstituteDataAttribute` helpers.
…ect context instantiation

- Removed `CreateDefaultLambdaHostContext` helper and updated tests to create context inline.
- Updated public test methods to use `internal` access modifier.
- Converted remaining `Fact` tests to `Theory` tests with `[AutoNSubstituteData]`.
- Improved test coverage by validating constructor dependencies explicitly.
- Cleaned up unused code regions and redundant comments for improved test readability.
…eter validation

- Replaced `ArgumentOutOfRangeException` with `ArgumentException` for improved clarity.
- Updated exception message to explicitly reference `InvocationCancellationBuffer` parameter.
- Removed redundant XML documentation to streamline code readability.
…ection.Get<T>`

- Merged nested `if` statements for improved readability and maintainability.
- Streamlined conditional checks for `_features` retrieval and addition logic.
- Updated assertions in unit tests to use generic type overloads for improved readability.
- Replaced `typeof(T)` with `.Be<T>()` for consistency across test cases.
- Replaced `ArgumentOutOfRangeException` with `ArgumentException` in test assertions.
- Introduced `CreateMocks` utility for initializing mocks in unit tests.
- Replaced inline mock initialization with `CreateMocks` to simplify setup.
- Added `Mocks` class to centralize mock dependencies for test cases.
- Updated `Dispose` and `DisposeAsync` tests to assert proper mock disposal behavior.
…ow on multiple calls

- Updated `DefaultLambdaHostContextTests` to assert that `DisposeAsync` can be called multiple times.
- Ensured the test uses `Should().NotThrowAsync` for improved assertion readability.
…atic

- Updated helper method to be static for clarity and to enforce non-reliance on instance state.
…ability

- Replaced inline assertions with Fluent Assertions to ensure consistent test styles.
- Removed redundant `StartAsync` unit test as it is no longer required.
- Updated `StopAsync` and `Dispose` tests to use lambda expressions for assertions.
- Changed `Dispose` tests to validate idempotency with improved assertion clarity.
…` feature extraction

- Updated `TryCreate` calls in unit tests to use `out var feature` for improved readability.
- Ensured consistent variable usage across test cases to enhance test clarity and maintainability.
- Standardized variable names to use PascalCase for improved readability and consistency.
- Updated mocks in `LambdaApplicationTests` to follow updated naming convention.
- Ensured all `Dispose` and `DisposeAsync` tests validate consistent mock behavior.
- Updated `LambdaApplicationTests` to assert `host` parameter name with correct casing.
- Ensured Fluent Assertions use consistent parameter naming format.
@j-d-ha j-d-ha changed the title refactor(core): refactor lambda application and builder interfaces refactor(core): refactor lambda application and builder Nov 23, 2025
@sonarqubecloud

Copy link
Copy Markdown

@j-d-ha
j-d-ha merged commit e287e97 into main Nov 23, 2025
9 checks passed
@j-d-ha
j-d-ha deleted the feature/#99-refactor-lambda-application-and-interfaces branch November 23, 2025 05:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change Introduces a breaking change type: refactor Code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add IHostedEnvironment to ILambdaApplication

1 participant