Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/getting-started/core-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,11 @@ graph LR
- Transients behave the same as ASP.NET Coreβ€”be mindful of repeated expensive setup.
- Never store scoped services on singletons; resolve them per invocation or pass data explicitly.

### Working with `ILambdaHostContext`
### Working with `ILambdaInvocationContext`

Every middleware component and handler can ask for `ILambdaHostContext`. Think of it as `HttpContext` for Lambda.
Every middleware component and handler can ask for `ILambdaInvocationContext`. Think of it as `HttpContext` for Lambda.

`ILambdaHostContext` exposes:
`ILambdaInvocationContext` exposes:

- `ServiceProvider` – the scoped provider for the current invocation.
- `CancellationToken` – fires `InvocationCancellationBuffer` before the hard Lambda timeout.
Expand All @@ -144,7 +144,7 @@ Every middleware component and handler can ask for `ILambdaHostContext`. Think o
```csharp title="Program.cs" linenums="1"
lambda.MapHandler(async (
[FromEvent] OrderRequest request,
ILambdaHostContext context,
ILambdaInvocationContext context,
IOrderService service,
CancellationToken ct
) =>
Expand All @@ -164,7 +164,7 @@ Handlers and lifecycle hooks can request multiple parameter types simultaneously

- `[FromEvent] T event` – Optional marker for the deserialized payload. Include it only when your Lambda expects input; the generator enforces that at most one parameter carries `[FromEvent]`.
- Services – Any registered service, keyed service (`[FromKeyedServices("key")]`), or options type.
- Context – `ILambdaHostContext` or the raw `ILambdaContext` from the AWS SDK.
- Context – `ILambdaInvocationContext` or the raw `ILambdaContext` from the AWS SDK.
- `CancellationToken` – Linked to end-to-end timeouts; pass it downstream.

## Middleware Pipeline
Expand Down Expand Up @@ -198,7 +198,7 @@ lambda.MapHandler(([FromEvent] OrderRequest order) => new OrderResponse(order.Id

## Feature System

Features provide decoupled access to invocation dataβ€”mirroring ASP.NET Core’s `HttpContext.Features` and Azure Functions’ binding features. Instead of injecting every dependency everywhere, middleware and handlers trade typed capabilities through the `ILambdaHostContext.Features` collection.
Features provide decoupled access to invocation dataβ€”mirroring ASP.NET Core’s `HttpContext.Features` and Azure Functions’ binding features. Instead of injecting every dependency everywhere, middleware and handlers trade typed capabilities through the `ILambdaInvocationContext.Features` collection.

Built-in feature types include:

Expand Down
10 changes: 5 additions & 5 deletions docs/guides/dependency-injection.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,16 @@ Lambda containers live across multiple invocations. Map the standard lifetimes t
- Transients work the same as in ASP.NET Core, but prefer Scoped unless you truly need a new instance
every time a constructor runs.

## Invocation Scope and `ILambdaHostContext`
## Invocation Scope and `ILambdaInvocationContext`

Every invocation gets its own scope. You can access it via the `ILambdaHostContext` and it is shared
Every invocation gets its own scope. You can access it via the `ILambdaInvocationContext` and it is shared
across middleware and handlers:

```csharp title="Handlers"
lambda.MapHandler(async (
[FromEvent] OrderRequest request,
IOrderService orders, // scoped service
ILambdaHostContext context, // framework context
ILambdaInvocationContext context, // framework context
CancellationToken cancellation // host-managed token
) =>
{
Expand All @@ -57,7 +57,7 @@ lambda.MapHandler(async (
});
```

`ILambdaHostContext` exposes:
`ILambdaInvocationContext` exposes:

- `ServiceProvider` – the scoped service provider for the invocation
- `CancellationToken` – automatically linked to Lambda remaining time
Expand All @@ -76,7 +76,7 @@ If your handler doesn't need the Lambda payload, omit the `[FromEvent]` paramete

## Middleware and Lifecycle Hooks: Source-Generated DI

- Middleware receives the invocation scope via the `ILambdaHostContext` argument. Resolve services with
- Middleware receives the invocation scope via the `ILambdaInvocationContext` argument. Resolve services with
`context.ServiceProvider` or create reusable middleware classes with constructor injection.
- `OnInit` and `OnShutdown` handlers now use the same source-generated dependency injection as your main
handlers. Each executes inside its own scoped service provider so you can warm caches, seed connections,
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/error-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ lambda.UseMiddleware(async (context, next) =>

- Register error-handling middleware first so it wraps every other component.
- Use the helper extensions (`context.GetResponse<T>()`, `context.GetEvent<T>()`, etc.) from
`FeatureLambdaHostContextExtensions` (they wrap `ILambdaHostContext.Features`) when you need to read
`FeatureLambdaInvocationContextExtensions` (they wrap `ILambdaInvocationContext.Features`) when you need to read
or replace the outgoing payload instead of throwing.
- Still rethrow fatal errors so the runtime produces accurate CloudWatch metrics and DLQ/SQS retries.

Expand Down
14 changes: 7 additions & 7 deletions docs/guides/handler-registration.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,15 @@ Handlers can mix lambda events with services, context objects, and cancellation
| `[FromEvent] T event` | Deserialized from the Lambda payload (or envelope). Optionalβ€”only include when the handler expects an input. |
| `IServiceType service` | Resolved from the DI container using the invocation scope. |
| `[FromKeyedServices("key")] IServiceType keyed` | Resolves a keyed service registered with `AddKeyed*`. Keys must be constants supported by the BCL. |
| `ILambdaHostContext context` | Framework context that extends `ILambdaContext`, exposes scoped `ServiceProvider`, `Items`, `Features`, `Properties`, and the invocation `CancellationToken`. |
| `ILambdaInvocationContext context` | Framework context that extends `ILambdaContext`, exposes scoped `ServiceProvider`, `Items`, `Features`, `Properties`, and the invocation `CancellationToken`. |
| `ILambdaContext lambdaContext` | Raw AWS Lambda context for folks that prefer the SDK contract. |
| `CancellationToken cancellationToken` | Cancels when `InvocationCancellationBuffer` elapses before the Lambda timeout. |

```csharp title="Program.cs" linenums="1"
lambda.MapHandler(async (
[FromEvent] OrderRequest request,
[FromKeyedServices("primary")] IOrderProcessor orderProcessor,
ILambdaHostContext context,
ILambdaInvocationContext context,
CancellationToken ct
) =>
{
Expand All @@ -128,7 +128,7 @@ lambda.MapHandler(async (
});
```

`ILambdaHostContext.ServiceProvider` is lazily created for each invocation. Prefer constructor- or parameter-injected services because they participate in disposal automatically, but the scoped provider is available for advanced scenarios.
`ILambdaInvocationContext.ServiceProvider` is lazily created for each invocation. Prefer constructor- or parameter-injected services because they participate in disposal automatically, but the scoped provider is available for advanced scenarios.

## Return Values and Serialization

Expand All @@ -138,16 +138,16 @@ The generator also emits serialization code for the delegate's return value. Sup
- `Task<T>` and `ValueTask<T>` for asynchronous responses.
- `Task` or `ValueTask` when no result should be written (Lambda receives `null`).

By default responses are serialized through the configured `ILambdaSerializer` (System.Text.Json unless you swap it). Envelope packages often provide specialized features that capture the response inside an `IResponseFeature`, so the `ILambdaHostContext` can retrieve or mutate it later.
By default responses are serialized through the configured `ILambdaSerializer` (System.Text.Json unless you swap it). Envelope packages often provide specialized features that capture the response inside an `IResponseFeature`, so the `ILambdaInvocationContext` can retrieve or mutate it later.

## Invocation Scope and Context

Each invocation receives its own dependency injection scope and `ILambdaHostContext`. Use it to share data across middleware and handlers without introducing service-locator patterns.
Each invocation receives its own dependency injection scope and `ILambdaInvocationContext`. Use it to share data across middleware and handlers without introducing service-locator patterns.

```csharp title="Program.cs" linenums="1"
lambda.MapHandler(async (
[FromEvent] ApiGatewayRequestEnvelope<Order> request,
ILambdaHostContext context,
ILambdaInvocationContext context,
ILogger<Program> logger,
CancellationToken ct
) =>
Expand Down Expand Up @@ -193,7 +193,7 @@ At runtime:
- Keep handlers thin. Delegate business logic to services so you can test them outside Lambda and reuse them across handlers.
- Respect the provided `CancellationToken`; `MinimalLambda` fires it `InvocationCancellationBuffer` before the hard Lambda timeout.
- Prefer strongly typed responses or envelopes instead of anonymous objectsβ€”serialization contracts stay predictable and versionable.
- Use `ILambdaHostContext.Features` (e.g., `context.GetEvent<T>()`) to decouple middleware from handlers when you need shared metadata.
- Use `ILambdaInvocationContext.Features` (e.g., `context.GetEvent<T>()`) to decouple middleware from handlers when you need shared metadata.
- Avoid resolving services manually from `IServiceProvider` unless absolutely necessary. Let the generator inject what you need, or expose a dedicated facade service.
- Prefer referencing a static method on a static class when you want to exercise the handler logic outside of the Lambda host. Mapping a method group (`lambda.MapHandler(MyHandler.HandleAsync);`) makes it trivial to unit test the handler by invoking it directly.

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/hosting.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Other customization hooks:
- `LambdaApplicationOptions.Args` – Flow command-line arguments into configuration.
- `builder.Services.ConfigureLambdaHostOptions(...)` – Override runtime behavior (Init/Shutdown timeouts, invocation cancellation buffer, output formatting).
- `builder.Services.AddLambdaSerializerWithContext<TContext>()` – Swap the default serializer with a source-generated one (or register any `ILambdaSerializer` manually).
- Register an `ILambdaHostContextAccessor` if you need to resolve `ILambdaHostContext` outside handlers/middleware.
- Register an `ILambdaInvocationContextAccessor` if you need to resolve `ILambdaInvocationContext` outside handlers/middleware.

## Build Phase

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/lifecycle-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ lambda.OnInit(async (ILambdaLifecycleContext context, ILogger<Program> logger) =
});
```

The `Properties` dictionary is backed by a thread-safe `ConcurrentDictionary<string, object?>` and is shared across all OnInit handlers. Properties set during OnInit are also available to invocation handlers via `ILambdaHostContext.Properties`.
The `Properties` dictionary is backed by a thread-safe `ConcurrentDictionary<string, object?>` and is shared across all OnInit handlers. Properties set during OnInit are also available to invocation handlers via `ILambdaInvocationContext.Properties`.

### Available Context Properties

Expand Down
8 changes: 4 additions & 4 deletions docs/guides/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ Output:
[Logging] After handler
```

## `ILambdaHostContext`
## `ILambdaInvocationContext`

Every middleware receives the same `ILambdaHostContext`, which is scoped to the invocation.
Every middleware receives the same `ILambdaInvocationContext`, which is scoped to the invocation.

```csharp title="Program.cs"
lambda.UseMiddleware(async (context, next) =>
Expand Down Expand Up @@ -84,7 +84,7 @@ Treat the delegate as the orchestration glue and push heavy lifting into service

## Working with Features

Features are type-keyed adapters stored inside `ILambdaHostContext.Features` (an
Features are type-keyed adapters stored inside `ILambdaInvocationContext.Features` (an
`IFeatureCollection`). They decouple middleware from handlers: a handler (or the framework) populates a
feature, middleware reads or mutates it, and nobody needs to inject each other through DI. The
collection lazily creates features by asking every registered `IFeatureProvider` to build them when
Expand Down Expand Up @@ -123,7 +123,7 @@ Common features:

### Type-Safe Feature Access

The framework provides convenient extension methods on `ILambdaHostContext` for type-safe event and response access, simplifying the feature access pattern shown above:
The framework provides convenient extension methods on `ILambdaInvocationContext` for type-safe event and response access, simplifying the feature access pattern shown above:

```csharp title="Program.cs"
lambda.UseMiddleware(async (context, next) =>
Expand Down
7 changes: 6 additions & 1 deletion examples/MinimalLambda.Example.Events/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MinimalLambda;
using MinimalLambda.Builder;
using MinimalLambda.Envelopes;
using MinimalLambda.Envelopes.ApiGateway;
Expand All @@ -26,7 +27,11 @@
var lambda = builder.Build();

lambda.MapHandler(
([FromEvent] ApiGatewayRequestEnvelope<Request> request, ILogger<Program> logger) =>
(
[FromEvent] ApiGatewayRequestEnvelope<Request> request,
ILogger<Program> logger,
ILambdaInvocationContext context
) =>
{
logger.LogInformation("In Handler. Payload: {Payload}", request.Body);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace MinimalLambda;
/// Encapsulates the information about a Lambda invocation. It extends
/// <see cref="ILambdaContext" /> with additional properties.
/// </summary>
public interface ILambdaHostContext : ILambdaContext
public interface ILambdaInvocationContext : ILambdaContext
{
/// <summary>
/// Gets the <see cref="CancellationToken" /> that signals a Lambda invocation is being
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
namespace MinimalLambda;

/// <summary>
/// Provides access to the <see cref="ILambdaHostContext" /> for the current Lambda
/// Provides access to the <see cref="ILambdaInvocationContext" /> for the current Lambda
/// invocation.
/// </summary>
/// <remarks>
/// This accessor is typically used to retrieve invocation context information from dependency
/// injection containers. It allows components to access the current Lambda context without
/// requiring it to be passed directly through method parameters.
/// </remarks>
public interface ILambdaHostContextAccessor
public interface ILambdaInvocationContextAccessor
{
/// <summary>Gets or sets the <see cref="ILambdaHostContext" /> for the current Lambda invocation.</summary>
/// <summary>Gets or sets the <see cref="ILambdaInvocationContext" /> for the current Lambda invocation.</summary>
/// <value>
/// The <see cref="ILambdaHostContext" /> for the current invocation, or <c>null</c> if no
/// The <see cref="ILambdaInvocationContext" /> for the current invocation, or <c>null</c> if no
/// invocation context is available.
/// </value>
ILambdaHostContext? LambdaHostContext { get; set; }
ILambdaInvocationContext? LambdaInvocationContext { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace MinimalLambda;
/// <remarks>
/// <para>
/// The <see cref="LambdaInvocationDelegate" /> is the core handler for processing Lambda
/// invocations. It receives an <see cref="ILambdaHostContext" /> that contains the
/// invocations. It receives an <see cref="ILambdaInvocationContext" /> that contains the
/// deserialized event, response storage, service provider, and other invocation-specific
/// information.
/// </para>
Expand All @@ -20,12 +20,12 @@ namespace MinimalLambda;
/// </para>
/// </remarks>
/// <param name="context">
/// The <see cref="ILambdaHostContext" /> containing invocation information,
/// The <see cref="ILambdaInvocationContext" /> containing invocation information,
/// services, event data, and a location to store the response.
/// </param>
/// <returns>A <see cref="Task" /> representing the asynchronous operation.</returns>
/// <seealso cref="LambdaInitDelegate" />
/// <seealso cref="LambdaShutdownDelegate" />
/// <seealso cref="ILambdaInvocationBuilder.Handle" />
/// <seealso cref="ILambdaInvocationBuilder.Use" />
public delegate Task LambdaInvocationDelegate(ILambdaHostContext context);
public delegate Task LambdaInvocationDelegate(ILambdaInvocationContext context);
4 changes: 2 additions & 2 deletions src/MinimalLambda.Abstractions/Features/IEventFeature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace MinimalLambda;
public interface IEventFeature
{
/// <summary>Gets the deserialized Lambda invocation event.</summary>
/// <param name="context">The <see cref="ILambdaHostContext" /> for the current invocation.</param>
/// <param name="context">The <see cref="ILambdaInvocationContext" /> for the current invocation.</param>
/// <returns>The deserialized event object, or <c>null</c> if the event cannot be deserialized.</returns>
object? GetEvent(ILambdaHostContext context);
object? GetEvent(ILambdaInvocationContext context);
}
4 changes: 2 additions & 2 deletions src/MinimalLambda.Abstractions/Features/IEventFeatureT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace MinimalLambda;
public interface IEventFeature<out T> : IEventFeature
{
/// <summary>Gets the deserialized Lambda invocation event of type <typeparamref name="T" />.</summary>
/// <param name="context">The <see cref="ILambdaHostContext" /> for the current invocation.</param>
/// <param name="context">The <see cref="ILambdaInvocationContext" /> for the current invocation.</param>
/// <returns>The deserialized event object of type <typeparamref name="T" />.</returns>
new T GetEvent(ILambdaHostContext context);
new T GetEvent(ILambdaInvocationContext context);
}
4 changes: 2 additions & 2 deletions src/MinimalLambda.Abstractions/Features/IResponseFeature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public interface IResponseFeature
object? GetResponse();

/// <summary>Serializes the response object to the Lambda response stream.</summary>
/// <param name="context">The <see cref="ILambdaHostContext" /> for the current invocation.</param>
void SerializeToStream(ILambdaHostContext context);
/// <param name="context">The <see cref="ILambdaInvocationContext" /> for the current invocation.</param>
void SerializeToStream(ILambdaInvocationContext context);
}
4 changes: 2 additions & 2 deletions src/MinimalLambda.Abstractions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ This design separates concerns between request/response handling, initialization
cleanup. See [MinimalLambda](../MinimalLambda/README.md) for detailed usage examples and the
complete builder API.

### ILambdaHostContext
### ILambdaInvocationContext

Encapsulates a single Lambda invocation and provides access to contextual information and services:

Expand Down Expand Up @@ -172,7 +172,7 @@ implementations.
**LambdaInvocationDelegate**

```csharp
Task LambdaInvocationDelegate(ILambdaHostContext context)
Task LambdaInvocationDelegate(ILambdaInvocationContext context)
```

Processes a Lambda invocation.
Expand Down
3 changes: 2 additions & 1 deletion src/MinimalLambda.SourceGenerators/GeneratorConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ internal static class TypeConstants
{
internal const string ILambdaContext = "global::Amazon.Lambda.Core.ILambdaContext";

internal const string ILambdaHostContext = "global::MinimalLambda.ILambdaHostContext";
internal const string ILambdaInvocationContext =
"global::MinimalLambda.ILambdaInvocationContext";

internal const string ILambdaLifecycleContext = "global::MinimalLambda.ILambdaLifecycleContext";

Expand Down
2 changes: 1 addition & 1 deletion src/MinimalLambda.SourceGenerators/Models/ParameterInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ private static (
{
TypeConstants.CancellationToken => (ParameterSource.CancellationToken, null),
TypeConstants.ILambdaContext => (ParameterSource.HostContext, null),
TypeConstants.ILambdaHostContext => (ParameterSource.HostContext, null),
TypeConstants.ILambdaInvocationContext => (ParameterSource.HostContext, null),
TypeConstants.ILambdaLifecycleContext => (ParameterSource.LifecycleContext, null),
_ => (ParameterSource.Service, null),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ private static HandlerArg[] BuildHandlerParameterAssignment(this DelegateInfo de
ParameterSource.Event =>
$"context.GetRequiredEvent<{param.TypeInfo.FullyQualifiedType}>()",

// ILambdaContext OR ILambdaHostContext -> use context directly
// ILambdaContext OR ILambdaInvocationContext -> use context directly
ParameterSource.HostContext => "context",

// CancellationToken -> get from context
Expand Down
Loading
Loading