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
15 changes: 13 additions & 2 deletions examples/examples-catalog.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,21 @@
"path": "./src/callback/callback.py"
},
{
"name": "Wait for Callback",
"name": "Wait for Callback Success",
"description": "Usage of context.wait_for_callback() to wait for external system responses",
"handler": "wait_for_callback.handler",
"integration": false,
"integration": true,
"durableConfig": {
"RetentionPeriodInDays": 7,
"ExecutionTimeout": 300
},
"path": "./src/wait_for_callback/wait_for_callback.py"
},
{
"name": "Wait for Callback Failure",
"description": "Usage of context.wait_for_callback() to wait for external system responses",
"handler": "wait_for_callback.handler",
"integration": true,
"durableConfig": {
"RetentionPeriodInDays": 7,
"ExecutionTimeout": 300
Expand Down
62 changes: 57 additions & 5 deletions examples/src/hello_world.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,62 @@
from typing import Any
"""Simple durable Lambda handler example.

from aws_durable_execution_sdk_python.context import DurableContext
This example demonstrates:
- Step execution with logging
- Wait operations (pausing without consuming resources)
- Replay-aware logging
- Returning a response
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from aws_durable_execution_sdk_python.config import Duration
from aws_durable_execution_sdk_python.context import DurableContext, durable_step
from aws_durable_execution_sdk_python.execution import durable_execution

if TYPE_CHECKING:
from aws_durable_execution_sdk_python.types import StepContext


@durable_step
def step_1(step_context: StepContext) -> None:
"""First step that logs a message."""
step_context.logger.info("Hello from step1")


@durable_step
def step_2(step_context: StepContext, status_code: int) -> str:
"""Second step that returns a message."""
step_context.logger.info("Returning message with status code: %d", status_code)
return f"Hello from Durable Lambda! (status: {status_code})"


@durable_execution
def handler(_event: Any, _context: DurableContext) -> str:
"""Simple hello world durable function."""
return "Hello World!"
def handler(event: Any, context: DurableContext) -> dict[str, Any]:
"""Durable Lambda handler with steps, waits, and logging.

Args:
event: Lambda event input
context: Durable execution context

Returns:
Response dictionary with statusCode and body
"""
# Execute Step #1 - logs a message
context.step(step_1())

# Pause for 10 seconds without consuming CPU cycles or incurring usage charges
# The execution will suspend here and resume after 10 seconds
context.wait(Duration.from_seconds(10))

context.logger.info("Waited for 10 seconds")

# Execute Step #2 - returns a message with status code
message = context.step(step_2(status_code=200))

# Return response
return {
"statusCode": 200,
"body": message,
}
17 changes: 12 additions & 5 deletions examples/test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
from typing import Any

import pytest
from aws_durable_execution_sdk_python.lambda_service import OperationPayload
from aws_durable_execution_sdk_python.lambda_service import (
ErrorObject,
OperationPayload,
)
from aws_durable_execution_sdk_python.serdes import ExtendedTypeSerDes

from aws_durable_execution_sdk_python_testing.runner import (
Expand Down Expand Up @@ -112,11 +115,15 @@ def run_async(
) -> str:
return self._runner.run_async(input=input, timeout=timeout)

def send_callback_success(self, callback_id: str) -> None:
self._runner.send_callback_success(callback_id=callback_id)
def send_callback_success(
self, callback_id: str, result: bytes | None = None
) -> None:
self._runner.send_callback_success(callback_id=callback_id, result=result)

def send_callback_failure(self, callback_id: str) -> None:
self._runner.send_callback_failure(callback_id=callback_id)
def send_callback_failure(
self, callback_id: str, error: ErrorObject | None = None
) -> None:
self._runner.send_callback_failure(callback_id=callback_id, error=error)

def send_callback_heartbeat(self, callback_id: str) -> None:
self._runner.send_callback_heartbeat(callback_id=callback_id)
Expand Down
7 changes: 5 additions & 2 deletions examples/test/test_hello_world.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
def test_hello_world(durable_runner):
"""Test hello world example."""
with durable_runner:
result = durable_runner.run(input="test", timeout=10)
result = durable_runner.run(input="test", timeout=30)

assert result.status is InvocationStatus.SUCCEEDED
assert deserialize_operation_payload(result.result) == "Hello World!"
assert deserialize_operation_payload(result.result) == {
"statusCode": 200,
"body": "Hello from Durable Lambda! (status: 200)",
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import pytest
from aws_durable_execution_sdk_python.execution import InvocationStatus
from aws_durable_execution_sdk_python.lambda_service import ErrorObject

from src.wait_for_callback import wait_for_callback


@pytest.mark.example
@pytest.mark.durable_execution(
handler=wait_for_callback.handler,
lambda_function_name="Wait For Callback Failure",
)
def test_wait_for_callback_failure(durable_runner):
with durable_runner:
execution_arn = durable_runner.run_async(input="test", timeout=30)
callback_id = durable_runner.wait_for_callback(execution_arn=execution_arn)
durable_runner.send_callback_failure(
callback_id=callback_id, error=ErrorObject.from_message("my callback error")
)
result = durable_runner.wait_for_result(execution_arn=execution_arn)

assert result.status is InvocationStatus.FAILED
assert isinstance(result.error, ErrorObject)
assert result.error.to_dict() == {
"ErrorMessage": "my callback error",
"ErrorType": "CallableRuntimeError",
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import pytest
from aws_durable_execution_sdk_python.execution import InvocationStatus

from src.wait_for_callback import wait_for_callback
from test.conftest import deserialize_operation_payload


@pytest.mark.example
@pytest.mark.durable_execution(
handler=wait_for_callback.handler,
lambda_function_name="Wait For Callback Success",
)
def test_wait_for_callback_success(durable_runner):
with durable_runner:
execution_arn = durable_runner.run_async(input="test", timeout=30)
callback_id = durable_runner.wait_for_callback(execution_arn=execution_arn)
durable_runner.send_callback_success(
callback_id=callback_id, result="callback success".encode()
)
result = durable_runner.wait_for_result(execution_arn=execution_arn)
assert result.status is InvocationStatus.SUCCEEDED
assert (
deserialize_operation_payload(result.result)
== "External system result: callback success"
)
Loading
Loading