Skip to content

Commit 3850837

Browse files
Alex Wangwangyb-A
authored andcommitted
examples: Add wait_for_callback examples
- Wait for callback examples - Add a helper method in the runner to get all nested operations - Update sam template
1 parent d212912 commit 3850837

21 files changed

+1202
-0
lines changed

examples/examples-catalog.json

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,105 @@
100100
},
101101
"path": "./src/wait_for_callback/wait_for_callback.py"
102102
},
103+
{
104+
"name": "Wait For Callback Success Anonymous",
105+
"description": "Usage of context.wait_for_callback() to wait for external system responses",
106+
"handler": "wait_for_callback_anonymous.handler",
107+
"integration": true,
108+
"durableConfig": {
109+
"RetentionPeriodInDays": 7,
110+
"ExecutionTimeout": 300
111+
},
112+
"path": "./src/wait_for_callback/wait_for_callback_anonymous.py"
113+
},
114+
{
115+
"name": "Wait For Callback Heartbeat Sends",
116+
"description": "Usage of context.wait_for_callback() to wait for external system responses",
117+
"handler": "wait_for_callback_heartbeat.handler",
118+
"integration": true,
119+
"durableConfig": {
120+
"RetentionPeriodInDays": 7,
121+
"ExecutionTimeout": 300
122+
},
123+
"path": "./src/wait_for_callback/wait_for_callback_heartbeat.py"
124+
},
125+
{
126+
"name": "Wait For Callback With Child Context",
127+
"description": "Usage of context.wait_for_callback() to wait for external system responses",
128+
"handler": "wait_for_callback_child.handler",
129+
"integration": true,
130+
"durableConfig": {
131+
"RetentionPeriodInDays": 7,
132+
"ExecutionTimeout": 300
133+
},
134+
"path": "./src/wait_for_callback/wait_for_callback_child.py"
135+
},
136+
{
137+
"name": "Wait For Callback Mixed Ops",
138+
"description": "Usage of context.wait_for_callback() to wait for external system responses",
139+
"handler": "wait_for_callback_mixed_ops.handler",
140+
"integration": true,
141+
"durableConfig": {
142+
"RetentionPeriodInDays": 7,
143+
"ExecutionTimeout": 300
144+
},
145+
"path": "./src/wait_for_callback/wait_for_callback_mixed_ops.py"
146+
},
147+
{
148+
"name": "Wait For Callback Multiple Invocations",
149+
"description": "Usage of context.wait_for_callback() to wait for external system responses",
150+
"handler": "wait_for_callback_multiple_invocations.handler",
151+
"integration": true,
152+
"durableConfig": {
153+
"RetentionPeriodInDays": 7,
154+
"ExecutionTimeout": 300
155+
},
156+
"path": "./src/wait_for_callback/wait_for_callback_multiple_invocations.py"
157+
},
158+
{
159+
"name": "Wait For Callback Failing Submitter Catchable",
160+
"description": "Usage of context.wait_for_callback() to wait for external system responses",
161+
"handler": "wait_for_callback_submitter_failure_catchable.handler",
162+
"integration": true,
163+
"durableConfig": {
164+
"RetentionPeriodInDays": 7,
165+
"ExecutionTimeout": 300
166+
},
167+
"path": "./src/wait_for_callback/wait_for_callback_submitter_failure_catchable.py"
168+
},
169+
{
170+
"name": "Wait For Callback Submitter Failure",
171+
"description": "Usage of context.wait_for_callback() to wait for external system responses",
172+
"handler": "wait_for_callback_submitter_failure.handler",
173+
"integration": true,
174+
"durableConfig": {
175+
"RetentionPeriodInDays": 7,
176+
"ExecutionTimeout": 300
177+
},
178+
"path": "./src/wait_for_callback/wait_for_callback_submitter_failure.py"
179+
},
180+
{
181+
"name": "Wait For Callback Serdes",
182+
"description": "Usage of context.wait_for_callback() to wait for external system responses",
183+
"handler": "wait_for_callback_serdes.handler",
184+
"integration": true,
185+
"durableConfig": {
186+
"RetentionPeriodInDays": 7,
187+
"ExecutionTimeout": 300
188+
},
189+
"path": "./src/wait_for_callback/wait_for_callback_serdes.py"
190+
},
191+
{
192+
"name": "Wait For Callback Nested",
193+
"description": "Usage of context.wait_for_callback() to wait for external system responses",
194+
"handler": "wait_for_callback_nested.handler",
195+
"integration": true,
196+
"durableConfig": {
197+
"RetentionPeriodInDays": 7,
198+
"ExecutionTimeout": 300
199+
},
200+
"path": "./src/wait_for_callback/wait_for_callback_nested.py"
201+
},
103202
{
104203
"name": "Run in Child Context",
105204
"description": "Usage of context.run_in_child_context() to execute operations in isolated contexts",
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""Demonstrates waitForCallback with anonymous (inline) submitter function."""
2+
3+
import time
4+
from typing import Any
5+
6+
from aws_durable_execution_sdk_python.context import DurableContext
7+
from aws_durable_execution_sdk_python.execution import durable_execution
8+
9+
10+
@durable_execution
11+
def handler(_event: Any, context: DurableContext) -> dict[str, Any]:
12+
"""Handler demonstrating waitForCallback with anonymous submitter."""
13+
result: str = context.wait_for_callback(lambda _: time.sleep(1))
14+
15+
return {
16+
"callbackResult": result,
17+
"completed": True,
18+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"""Demonstrates waitForCallback operations within child contexts."""
2+
3+
from typing import Any
4+
5+
from aws_durable_execution_sdk_python.context import (
6+
DurableContext,
7+
durable_with_child_context,
8+
)
9+
from aws_durable_execution_sdk_python.execution import durable_execution
10+
from aws_durable_execution_sdk_python.config import Duration
11+
12+
13+
@durable_with_child_context
14+
def child_context_with_callback(child_context: DurableContext) -> dict[str, Any]:
15+
"""Child context containing wait and callback operations."""
16+
child_context.wait(Duration.from_seconds(1), name="child-wait")
17+
18+
child_callback_result: str = child_context.wait_for_callback(
19+
lambda _: None, name="child-callback-op"
20+
)
21+
22+
return {
23+
"childResult": child_callback_result,
24+
"childProcessed": True,
25+
}
26+
27+
28+
@durable_execution
29+
def handler(_event: Any, context: DurableContext) -> dict[str, Any]:
30+
"""Handler demonstrating waitForCallback within child contexts."""
31+
parent_result: str = context.wait_for_callback(
32+
lambda _: None, name="parent-callback-op"
33+
)
34+
35+
child_context_result: dict[str, Any] = context.run_in_child_context(
36+
child_context_with_callback(), name="child-context-with-callback"
37+
)
38+
39+
return {
40+
"parentResult": parent_result,
41+
"childContextResult": child_context_result,
42+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Demonstrates sending heartbeats during long-running callback processing."""
2+
3+
import time
4+
from typing import Any
5+
6+
from aws_durable_execution_sdk_python.context import DurableContext
7+
from aws_durable_execution_sdk_python.execution import durable_execution
8+
from aws_durable_execution_sdk_python.config import Duration
9+
from aws_durable_execution_sdk_python.config import WaitForCallbackConfig
10+
11+
12+
def submitter(_callback_id: str) -> None:
13+
"""Simulate long-running submitter function."""
14+
time.sleep(5)
15+
return None
16+
17+
18+
@durable_execution
19+
def handler(event: dict[str, Any], context: DurableContext) -> dict[str, Any]:
20+
"""Handler demonstrating waitForCallback with heartbeat timeout."""
21+
22+
config = WaitForCallbackConfig(
23+
timeout=Duration.from_seconds(120), heartbeat_timeout=Duration.from_seconds(15)
24+
)
25+
26+
result: str = context.wait_for_callback(submitter, config=config)
27+
28+
return {
29+
"callbackResult": result,
30+
"completed": True,
31+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""Demonstrates waitForCallback combined with steps, waits, and other operations."""
2+
3+
import time
4+
from typing import Any
5+
6+
from aws_durable_execution_sdk_python.context import DurableContext
7+
from aws_durable_execution_sdk_python.execution import durable_execution
8+
from aws_durable_execution_sdk_python.config import Duration
9+
10+
11+
@durable_execution
12+
def handler(_event: Any, context: DurableContext) -> dict[str, Any]:
13+
"""Handler demonstrating waitForCallback mixed with other operations."""
14+
# Mix waitForCallback with other operation types
15+
context.wait(Duration.from_seconds(1), name="initial-wait")
16+
17+
step_result: dict[str, Any] = context.step(
18+
lambda _: {"userId": 123, "name": "John Doe"},
19+
name="fetch-user-data",
20+
)
21+
22+
def submitter(_) -> None:
23+
"""Submitter uses data from previous step."""
24+
time.sleep(0.1)
25+
return None
26+
27+
callback_result: str = context.wait_for_callback(
28+
submitter,
29+
name="wait-for-callback",
30+
)
31+
32+
context.wait(Duration.from_seconds(2), name="final-wait")
33+
34+
final_step: dict[str, Any] = context.step(
35+
lambda _: {
36+
"status": "completed",
37+
"timestamp": int(time.time() * 1000),
38+
},
39+
name="finalize-processing",
40+
)
41+
42+
return {
43+
"stepResult": step_result,
44+
"callbackResult": callback_result,
45+
"finalStep": final_step,
46+
"workflowCompleted": True,
47+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""Demonstrates multiple invocations tracking with waitForCallback operations across different invocations."""
2+
3+
from typing import Any
4+
5+
from aws_durable_execution_sdk_python.context import DurableContext
6+
from aws_durable_execution_sdk_python.execution import durable_execution
7+
from aws_durable_execution_sdk_python.config import Duration
8+
9+
10+
@durable_execution
11+
def handler(_event: Any, context: DurableContext) -> dict[str, Any]:
12+
"""Handler demonstrating multiple invocations with waitForCallback operations."""
13+
# First invocation - wait operation
14+
context.wait(Duration.from_seconds(1), name="wait-invocation-1")
15+
16+
# First callback operation
17+
def first_submitter(callback_id: str) -> None:
18+
"""Submitter for first callback."""
19+
print(f"First callback submitted with ID: {callback_id}")
20+
return None
21+
22+
callback_result_1: str = context.wait_for_callback(
23+
first_submitter,
24+
name="first-callback",
25+
)
26+
27+
# Step operation between callbacks
28+
step_result: dict[str, Any] = context.step(
29+
lambda _: {"processed": True, "step": 1},
30+
name="process-callback-data",
31+
)
32+
33+
# Second invocation - another wait operation
34+
context.wait(Duration.from_seconds(1), name="wait-invocation-2")
35+
36+
# Second callback operation
37+
def second_submitter(callback_id: str) -> None:
38+
"""Submitter for second callback."""
39+
print(f"Second callback submitted with ID: {callback_id}")
40+
return None
41+
42+
callback_result_2: str = context.wait_for_callback(
43+
second_submitter,
44+
name="second-callback",
45+
)
46+
47+
# Final invocation returns complete result
48+
return {
49+
"firstCallback": callback_result_1,
50+
"secondCallback": callback_result_2,
51+
"stepResult": step_result,
52+
"invocationCount": "multiple",
53+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""Demonstrates nested waitForCallback operations across multiple child context levels."""
2+
3+
from typing import Any
4+
5+
from aws_durable_execution_sdk_python.context import (
6+
DurableContext,
7+
durable_with_child_context,
8+
)
9+
from aws_durable_execution_sdk_python.execution import durable_execution
10+
from aws_durable_execution_sdk_python.config import Duration
11+
12+
13+
@durable_with_child_context
14+
def inner_child_context(inner_child_ctx: DurableContext) -> dict[str, Any]:
15+
"""Inner child context with deep nested callback."""
16+
inner_child_ctx.wait(Duration.from_seconds(5), name="deep-wait")
17+
18+
nested_callback_result: str = inner_child_ctx.wait_for_callback(
19+
lambda _: None,
20+
name="nested-callback-op",
21+
)
22+
23+
return {
24+
"nestedCallback": nested_callback_result,
25+
"deepLevel": "inner-child",
26+
}
27+
28+
29+
@durable_with_child_context
30+
def outer_child_context(outer_child_ctx: DurableContext) -> dict[str, Any]:
31+
"""Outer child context with inner callback and nested context."""
32+
inner_result: str = outer_child_ctx.wait_for_callback(
33+
lambda _: None,
34+
name="inner-callback-op",
35+
)
36+
37+
# Nested child context with another callback
38+
deep_nested_result: dict[str, Any] = outer_child_ctx.run_in_child_context(
39+
inner_child_context(),
40+
name="inner-child-context",
41+
)
42+
43+
return {
44+
"innerCallback": inner_result,
45+
"deepNested": deep_nested_result,
46+
"level": "outer-child",
47+
}
48+
49+
50+
@durable_execution
51+
def handler(_event: Any, context: DurableContext) -> dict[str, Any]:
52+
"""Handler demonstrating nested waitForCallback operations across multiple levels."""
53+
outer_result: str = context.wait_for_callback(
54+
lambda _: None,
55+
name="outer-callback-op",
56+
)
57+
58+
nested_result: dict[str, Any] = context.run_in_child_context(
59+
outer_child_context(),
60+
name="outer-child-context",
61+
)
62+
63+
return {
64+
"outerCallback": outer_result,
65+
"nestedResults": nested_result,
66+
}

0 commit comments

Comments
 (0)