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
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import software.amazon.lambda.durable.client.DurableExecutionClient;
import software.amazon.lambda.durable.client.LambdaDurableFunctionsClient;
import software.amazon.lambda.durable.logging.LoggerConfig;
import software.amazon.lambda.durable.plugin.PluginRunner;
import software.amazon.lambda.durable.retry.PollingStrategies;
import software.amazon.lambda.durable.retry.PollingStrategy;
import software.amazon.lambda.durable.serde.JacksonSerDes;
Expand Down Expand Up @@ -94,6 +95,7 @@ public final class DurableConfig {
private final LoggerConfig loggerConfig;
private final PollingStrategy pollingStrategy;
private final Duration checkpointDelay;
private final PluginRunner pluginRunner;

private DurableConfig(Builder builder) {
this.durableExecutionClient = Objects.requireNonNullElseGet(
Expand All @@ -104,6 +106,7 @@ private DurableConfig(Builder builder) {
this.loggerConfig = Objects.requireNonNullElseGet(builder.loggerConfig, LoggerConfig::defaults);
this.pollingStrategy = Objects.requireNonNullElse(builder.pollingStrategy, PollingStrategies.Presets.DEFAULT);
this.checkpointDelay = Objects.requireNonNullElseGet(builder.checkpointDelay, () -> Duration.ofSeconds(0));
this.pluginRunner = PluginRunner.noOp();

validateConfiguration();
}
Expand Down Expand Up @@ -180,6 +183,20 @@ public Duration getCheckpointDelay() {
return checkpointDelay;
}

/**
* Gets the plugin runner that dispatches lifecycle events to registered plugins.
*
* <p>Currently returns a no-op runner. Plugin registration via config will be added when the plugin system is fully
* wired.
*
* @return PluginRunner instance (always no-op until plugin wiring is complete)
* @deprecated This is a preview API that is experimental and may be changed or removed in future releases.
*/
@Deprecated
public PluginRunner getPluginRunner() {
return pluginRunner;
}

public void validateConfiguration() {
if (getDurableExecutionClient() == null) {
throw new IllegalStateException("DurableExecutionClient configuration failed");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package software.amazon.lambda.durable.plugin;

/**
* Plugin interface for instrumenting durable execution lifecycle events.
*
* <p>Implement this interface to integrate observability tools (OpenTelemetry, Datadog, etc.) with the durable
* execution SDK. The SDK calls these hooks at key lifecycle points without requiring modifications to core SDK code.
*
* <p>All methods have default no-op implementations, allowing plugins to override only the hooks they need.
*
* <p>Plugin errors are isolated — exceptions thrown by plugin methods are caught and logged but never disrupt SDK
* execution.
*
* @deprecated This is a preview API that is experimental and may be changed or removed in future releases.
*/
@Deprecated
public interface DurableExecutionPlugin {

// ─── Invocation-level hooks ──────────────────────────────────────────

/**
* Called at the start of each Lambda invocation. Use to set up per-invocation state (trace ID, invocation span).
*
* <p>Check {@link InvocationInfo#isFirstInvocation()} to detect the first invocation of an execution (useful for
* sampling decisions or execution-level span creation).
*/
default void onInvocationStart(InvocationInfo info) {}

/**
* Called at the end of each Lambda invocation. Use to flush spans/metrics before Lambda freezes.
*
* <p>This hook is awaited — the SDK blocks until it returns. This is the only safe flush point before Lambda
* freezes the execution environment.
*
* <p>Check {@link InvocationEndInfo#invocationStatus()} to detect if the execution reached a terminal state in this
* invocation (useful for writing summary records or flushing final data).
*/
default void onInvocationEnd(InvocationEndInfo info) {}

// ─── Operation-level hooks ───────────────────────────────────────────

/** Called when an operation starts (including replay). Use for logging/metrics that want replay visibility. */
default void onOperationStart(OperationInfo info) {}

/**
* Called when an operation reaches a terminal status for the first time (not on replay).
*
* <p>The OTel plugin creates operation spans here with backfilled start/end timestamps.
*/
default void onOperationEnd(OperationEndInfo info) {}

// ─── User function hooks ─────────────────────────────────────────────

/**
* Called when a user-provided function starts executing. This fires for both step attempts (with {@code attempt}
* set) and child context functions (with {@code attempt} null).
*
* <p>This hook fires on the same thread as user code, so plugins can set OTel context via
* {@code Context.makeCurrent()} here.
*/
default void onUserFunctionStart(UserFunctionStartInfo info) {}

/**
* Called when a user-provided function finishes executing. This fires for both step attempts and child context
* functions.
*
* <p>This hook fires on the same thread as user code, so plugins can close OTel scopes here.
*/
default void onUserFunctionEnd(UserFunctionEndInfo info) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package software.amazon.lambda.durable.plugin;

/**
* Information provided at the end of a Lambda invocation.
*
* @param requestId the Lambda request ID for this invocation
* @param executionArn the durable execution ARN
* @param isFirstInvocation true if this is the first invocation of the execution
* @param invocationStatus the invocation outcome (SUCCEEDED, FAILED, or PENDING)
* @param executionError non-null if the execution failed
* @deprecated This is a preview API that is experimental and may be changed or removed in future releases.
*/
@Deprecated
public record InvocationEndInfo(
String requestId,
String executionArn,
boolean isFirstInvocation,
InvocationStatus invocationStatus,
Throwable executionError) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package software.amazon.lambda.durable.plugin;

/**
* Invocation-level information available to plugin hooks.
*
* @param requestId the Lambda request ID for this invocation
* @param executionArn the durable execution ARN
* @param isFirstInvocation true if this is the first invocation of the execution (not a replay invocation)
* @deprecated This is a preview API that is experimental and may be changed or removed in future releases.
*/
@Deprecated
public record InvocationInfo(String requestId, String executionArn, boolean isFirstInvocation) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package software.amazon.lambda.durable.plugin;

/**
* Status of a Lambda invocation at the end of its execution.
*
* @deprecated This is a preview API that is experimental and may be changed or removed in future releases.
*/
@Deprecated
public enum InvocationStatus {
/** Execution completed successfully in this invocation. */
SUCCEEDED,
/** Execution failed in this invocation. */
FAILED,
/** Execution suspended — will resume in a future invocation. */
PENDING
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package software.amazon.lambda.durable.plugin;

import java.time.Instant;

/**
* Extended operation information for operation end events.
*
* @param id operation ID — hashed
* @param rawId operation ID — unhashed
* @param name human-readable operation name (may be null)
* @param type operation type
* @param subType operation sub-type (may be null)
* @param parentId parent operation ID — hashed (null for root-level operations)
* @param rawParentId parent operation ID — unhashed (null for root-level operations)
* @param startTimestamp when the operation started
* @param endTimestamp when the operation ended
* @param error non-null if the operation failed
* @deprecated This is a preview API that is experimental and may be changed or removed in future releases.
*/
@Deprecated
public record OperationEndInfo(
String id,
String rawId,
String name,
String type,
String subType,
String parentId,
String rawParentId,
Instant startTimestamp,
Instant endTimestamp,
Throwable error) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package software.amazon.lambda.durable.plugin;

import java.time.Instant;

/**
* Operation-level information available to plugin hooks.
*
* <p>Field names mirror the {@code Operation} type from the AWS SDK for consistency.
*
* @param id operation ID — hashed (unique within the execution)
* @param rawId operation ID — unhashed (e.g. "1", "2", "hash(1)-1" for child contexts)
* @param name human-readable operation name (may be null)
* @param type operation type (STEP, WAIT, CONTEXT, CHAINED_INVOKE, CALLBACK)
* @param subType operation sub-type (Map, Parallel, RunInChildContext, WaitForCondition, etc.) — may be null
* @param parentId parent operation ID — hashed (null for root-level operations)
* @param rawParentId parent operation ID — unhashed (null for root-level operations)
* @param startTimestamp when the operation started (may be from a prior invocation)
* @param endTimestamp when the operation ended (null if still running)
* @deprecated This is a preview API that is experimental and may be changed or removed in future releases.
*/
@Deprecated
public record OperationInfo(
String id,
String rawId,
String name,
String type,
String subType,
String parentId,
String rawParentId,
Instant startTimestamp,
Instant endTimestamp) {}
Loading