@@ -599,8 +599,6 @@ def _apply_query_workflow(
599
599
) -> None :
600
600
# Wrap entire bunch of work in a task
601
601
async def run_query () -> None :
602
- command = self ._add_command ()
603
- command .respond_to_query .query_id = job .query_id
604
602
try :
605
603
with self ._as_read_only ():
606
604
# Named query or dynamic
@@ -632,11 +630,13 @@ async def run_query() -> None:
632
630
raise ValueError (
633
631
f"Expected 1 result payload, got { len (result_payloads )} "
634
632
)
635
- command . respond_to_query . succeeded . response . CopyFrom (
636
- result_payloads [ 0 ]
637
- )
633
+ command = self . _add_command ()
634
+ command . respond_to_query . query_id = job . query_id
635
+ command . respond_to_query . succeeded . response . CopyFrom ( result_payloads [ 0 ] )
638
636
except Exception as err :
639
637
try :
638
+ command = self ._add_command ()
639
+ command .respond_to_query .query_id = job .query_id
640
640
self ._failure_converter .to_failure (
641
641
err ,
642
642
self ._payload_converter ,
@@ -1427,7 +1427,7 @@ async def run_activity() -> Any:
1427
1427
await asyncio .sleep (
1428
1428
err .backoff .backoff_duration .ToTimedelta ().total_seconds ()
1429
1429
)
1430
- handle ._apply_schedule_command (self . _add_command (), err .backoff )
1430
+ handle ._apply_schedule_command (err .backoff )
1431
1431
# We have to put the handle back on the pending activity
1432
1432
# dict with its new seq
1433
1433
self ._pending_activities [handle ._seq ] = handle
@@ -1437,35 +1437,41 @@ async def run_activity() -> Any:
1437
1437
1438
1438
# Create the handle and set as pending
1439
1439
handle = _ActivityHandle (self , input , run_activity ())
1440
- handle ._apply_schedule_command (self . _add_command () )
1440
+ handle ._apply_schedule_command ()
1441
1441
self ._pending_activities [handle ._seq ] = handle
1442
1442
return handle
1443
1443
1444
1444
async def _outbound_signal_child_workflow (
1445
1445
self , input : SignalChildWorkflowInput
1446
1446
) -> None :
1447
+ payloads = (
1448
+ self ._payload_converter .to_payloads (input .args ) if input .args else None
1449
+ )
1447
1450
command = self ._add_command ()
1448
1451
v = command .signal_external_workflow_execution
1449
1452
v .child_workflow_id = input .child_workflow_id
1450
1453
v .signal_name = input .signal
1451
- if input . args :
1452
- v .args .extend (self . _payload_converter . to_payloads ( input . args ) )
1454
+ if payloads :
1455
+ v .args .extend (payloads )
1453
1456
if input .headers :
1454
1457
temporalio .common ._apply_headers (input .headers , v .headers )
1455
1458
await self ._signal_external_workflow (command )
1456
1459
1457
1460
async def _outbound_signal_external_workflow (
1458
1461
self , input : SignalExternalWorkflowInput
1459
1462
) -> None :
1463
+ payloads = (
1464
+ self ._payload_converter .to_payloads (input .args ) if input .args else None
1465
+ )
1460
1466
command = self ._add_command ()
1461
1467
v = command .signal_external_workflow_execution
1462
1468
v .workflow_execution .namespace = input .namespace
1463
1469
v .workflow_execution .workflow_id = input .workflow_id
1464
1470
if input .workflow_run_id :
1465
1471
v .workflow_execution .run_id = input .workflow_run_id
1466
1472
v .signal_name = input .signal
1467
- if input . args :
1468
- v .args .extend (self . _payload_converter . to_payloads ( input . args ) )
1473
+ if payloads :
1474
+ v .args .extend (payloads )
1469
1475
if input .headers :
1470
1476
temporalio .common ._apply_headers (input .headers , v .headers )
1471
1477
await self ._signal_external_workflow (command )
@@ -1510,7 +1516,7 @@ async def run_child() -> Any:
1510
1516
handle = _ChildWorkflowHandle (
1511
1517
self , self ._next_seq ("child_workflow" ), input , run_child ()
1512
1518
)
1513
- handle ._apply_start_command (self . _add_command () )
1519
+ handle ._apply_start_command ()
1514
1520
self ._pending_child_workflows [handle ._seq ] = handle
1515
1521
1516
1522
# Wait on start before returning
@@ -1761,7 +1767,7 @@ async def _run_top_level_workflow_function(self, coro: Awaitable[None]) -> None:
1761
1767
await coro
1762
1768
except _ContinueAsNewError as err :
1763
1769
logger .debug ("Workflow requested continue as new" )
1764
- err ._apply_command (self . _add_command () )
1770
+ err ._apply_command ()
1765
1771
except (Exception , asyncio .CancelledError ) as err :
1766
1772
# During tear down we can ignore exceptions. Technically the
1767
1773
# command-adding done later would throw a not-in-workflow exception
@@ -1776,7 +1782,7 @@ async def _run_top_level_workflow_function(self, coro: Awaitable[None]) -> None:
1776
1782
# Handle continue as new
1777
1783
if isinstance (err , _ContinueAsNewError ):
1778
1784
logger .debug ("Workflow requested continue as new" )
1779
- err ._apply_command (self . _add_command () )
1785
+ err ._apply_command ()
1780
1786
return
1781
1787
1782
1788
logger .debug (
@@ -2261,11 +2267,18 @@ def _resolve_backoff(
2261
2267
2262
2268
def _apply_schedule_command (
2263
2269
self ,
2264
- command : temporalio .bridge .proto .workflow_commands .WorkflowCommand ,
2265
2270
local_backoff : Optional [
2266
2271
temporalio .bridge .proto .activity_result .DoBackoff
2267
2272
] = None ,
2268
2273
) -> None :
2274
+ # Convert arguments before creating command in case it raises error
2275
+ payloads = (
2276
+ self ._instance ._payload_converter .to_payloads (self ._input .args )
2277
+ if self ._input .args
2278
+ else None
2279
+ )
2280
+
2281
+ command = self ._instance ._add_command ()
2269
2282
# TODO(cretz): Why can't MyPy infer this?
2270
2283
v : Union [
2271
2284
temporalio .bridge .proto .workflow_commands .ScheduleActivity ,
@@ -2280,10 +2293,8 @@ def _apply_schedule_command(
2280
2293
v .activity_type = self ._input .activity
2281
2294
if self ._input .headers :
2282
2295
temporalio .common ._apply_headers (self ._input .headers , v .headers )
2283
- if self ._input .args :
2284
- v .arguments .extend (
2285
- self ._instance ._payload_converter .to_payloads (self ._input .args )
2286
- )
2296
+ if payloads :
2297
+ v .arguments .extend (payloads )
2287
2298
if self ._input .schedule_to_close_timeout :
2288
2299
v .schedule_to_close_timeout .FromTimedelta (
2289
2300
self ._input .schedule_to_close_timeout
@@ -2403,20 +2414,23 @@ def _resolve_failure(self, err: BaseException) -> None:
2403
2414
# future
2404
2415
self ._result_fut .set_result (None )
2405
2416
2406
- def _apply_start_command (
2407
- self ,
2408
- command : temporalio .bridge .proto .workflow_commands .WorkflowCommand ,
2409
- ) -> None :
2417
+ def _apply_start_command (self ) -> None :
2418
+ # Convert arguments before creating command in case it raises error
2419
+ payloads = (
2420
+ self ._instance ._payload_converter .to_payloads (self ._input .args )
2421
+ if self ._input .args
2422
+ else None
2423
+ )
2424
+
2425
+ command = self ._instance ._add_command ()
2410
2426
v = command .start_child_workflow_execution
2411
2427
v .seq = self ._seq
2412
2428
v .namespace = self ._instance ._info .namespace
2413
2429
v .workflow_id = self ._input .id
2414
2430
v .workflow_type = self ._input .workflow
2415
2431
v .task_queue = self ._input .task_queue or self ._instance ._info .task_queue
2416
- if self ._input .args :
2417
- v .input .extend (
2418
- self ._instance ._payload_converter .to_payloads (self ._input .args )
2419
- )
2432
+ if payloads :
2433
+ v .input .extend (payloads )
2420
2434
if self ._input .execution_timeout :
2421
2435
v .workflow_execution_timeout .FromTimedelta (self ._input .execution_timeout )
2422
2436
if self ._input .run_timeout :
@@ -2520,19 +2534,31 @@ def __init__(
2520
2534
self ._instance = instance
2521
2535
self ._input = input
2522
2536
2523
- def _apply_command (
2524
- self , command : temporalio .bridge .proto .workflow_commands .WorkflowCommand
2525
- ) -> None :
2537
+ def _apply_command (self ) -> None :
2538
+ # Convert arguments before creating command in case it raises error
2539
+ payloads = (
2540
+ self ._instance ._payload_converter .to_payloads (self ._input .args )
2541
+ if self ._input .args
2542
+ else None
2543
+ )
2544
+ memo_payloads = (
2545
+ {
2546
+ k : self ._instance ._payload_converter .to_payloads ([val ])[0 ]
2547
+ for k , val in self ._input .memo .items ()
2548
+ }
2549
+ if self ._input .memo
2550
+ else None
2551
+ )
2552
+
2553
+ command = self ._instance ._add_command ()
2526
2554
v = command .continue_as_new_workflow_execution
2527
2555
v .SetInParent ()
2528
2556
if self ._input .workflow :
2529
2557
v .workflow_type = self ._input .workflow
2530
2558
if self ._input .task_queue :
2531
2559
v .task_queue = self ._input .task_queue
2532
- if self ._input .args :
2533
- v .arguments .extend (
2534
- self ._instance ._payload_converter .to_payloads (self ._input .args )
2535
- )
2560
+ if payloads :
2561
+ v .arguments .extend (payloads )
2536
2562
if self ._input .run_timeout :
2537
2563
v .workflow_run_timeout .FromTimedelta (self ._input .run_timeout )
2538
2564
if self ._input .task_timeout :
@@ -2541,11 +2567,9 @@ def _apply_command(
2541
2567
temporalio .common ._apply_headers (self ._input .headers , v .headers )
2542
2568
if self ._input .retry_policy :
2543
2569
self ._input .retry_policy .apply_to_proto (v .retry_policy )
2544
- if self ._input .memo :
2545
- for k , val in self ._input .memo .items ():
2546
- v .memo [k ].CopyFrom (
2547
- self ._instance ._payload_converter .to_payloads ([val ])[0 ]
2548
- )
2570
+ if memo_payloads :
2571
+ for k , val in memo_payloads .items ():
2572
+ v .memo [k ].CopyFrom (val )
2549
2573
if self ._input .search_attributes :
2550
2574
_encode_search_attributes (
2551
2575
self ._input .search_attributes , v .search_attributes
0 commit comments