99
1010from aws_durable_execution_sdk_python .exceptions import ValidationError
1111
12+
1213P = TypeVar ("P" ) # Payload type
1314R = TypeVar ("R" ) # Result type
1415T = TypeVar ("T" )
@@ -245,6 +246,41 @@ class ParallelConfig:
245246 nesting_type : NestingType = NestingType .NESTED
246247
247248
249+ @dataclass (frozen = True )
250+ class ParallelBranch (Generic [T ]):
251+ """A named branch for parallel execution.
252+
253+ Use this to provide custom names for parallel branches, improving
254+ observability in execution history.
255+
256+ Type Parameters:
257+ T: The return type of the branch function.
258+
259+ Args:
260+ func: The callable to execute in this branch. Receives a DurableContext.
261+ name: Optional custom name for this branch. When provided, replaces
262+ the default "parallel-branch-{index}" naming in execution history.
263+ This affects observability but not replay determinism.
264+
265+ Example:
266+ context.parallel(
267+ functions=[
268+ ParallelBranch(func=lambda ctx: fetch_user(ctx), name="fetch-user-data"),
269+ ParallelBranch(func=lambda ctx: fetch_orders(ctx), name="fetch-order-history"),
270+ ],
271+ name="load-data",
272+ config=ParallelConfig(max_concurrency=2),
273+ )
274+ """
275+
276+ func : Callable
277+ name : str | None = None
278+
279+ def __call__ (self , * args , ** kwargs ):
280+ """Delegate to the wrapped function, making ParallelBranch itself callable."""
281+ return self .func (* args , ** kwargs )
282+
283+
248284class StepSemantics (Enum ):
249285 AT_MOST_ONCE_PER_RETRY = "AT_MOST_ONCE_PER_RETRY"
250286 AT_LEAST_ONCE_PER_RETRY = "AT_LEAST_ONCE_PER_RETRY"
@@ -354,12 +390,15 @@ class ItemBatcher(Generic[T]):
354390
355391
356392@dataclass (frozen = True )
357- class MapConfig :
393+ class MapConfig ( Generic [ T ]) :
358394 """Configuration options for map operations over collections.
359395
360396 This class configures how map operations process collections of items,
361397 including concurrency, batching, completion criteria, and serialization.
362398
399+ Type Parameters:
400+ T: The type of items being processed in the map operation.
401+
363402 Args:
364403 max_concurrency: Maximum number of items to process concurrently.
365404 If None, no limit is imposed and all items are processed concurrently.
@@ -402,13 +441,25 @@ class MapConfig:
402441 - NESTED: Each item runs in its own isolated context (default)
403442 - FLAT: All items share the same parent context
404443
444+ item_namer: Optional callable to generate custom names for each map iteration.
445+ When provided, replaces the default "map-item-{index}" naming scheme.
446+ Receives the item and its index, and returns a string name for that iteration.
447+ This affects observability (execution history names) but not replay determinism.
448+ If None, uses the default naming: "map-item-{index}".
449+
405450 Example:
406451 # Process 5 items at a time, batch by count, require all to succeed
407452 config = MapConfig(
408453 max_concurrency=5,
409454 item_batcher=ItemBatcher(max_items_per_batch=10),
410455 completion_config=CompletionConfig.all_successful()
411456 )
457+
458+ # With custom iteration names
459+ config = MapConfig(
460+ max_concurrency=5,
461+ item_namer=lambda item, index: f"process-order-{item.id}"
462+ )
412463 """
413464
414465 max_concurrency : int | None = None
@@ -418,6 +469,7 @@ class MapConfig:
418469 item_serdes : SerDes | None = None
419470 summary_generator : SummaryGenerator | None = None
420471 nesting_type : NestingType = NestingType .NESTED
472+ item_namer : Callable [[T , int ], str ] | None = None
421473
422474
423475@dataclass (frozen = True )
0 commit comments