20
20
from dispatch .coroutine import AllDirective , AnyDirective , AnyException , RaceDirective
21
21
from dispatch .error import IncompatibleStateError
22
22
from dispatch .experimental .durable .function import DurableCoroutine , DurableGenerator
23
- from dispatch .proto import Call , Error , Input , Output
23
+ from dispatch .proto import Call , Error , Input , Output , TailCall
24
24
from dispatch .status import Status
25
25
26
26
logger = logging .getLogger (__name__ )
@@ -37,6 +37,8 @@ class CoroutineResult:
37
37
coroutine_id : CoroutineID
38
38
value : Optional [Any ] = None
39
39
error : Optional [Exception ] = None
40
+ call : Optional [Call ] = None
41
+ status : Status = Status .OK
40
42
41
43
42
44
@dataclass
@@ -438,6 +440,10 @@ def _run(self, input: Input) -> Output:
438
440
coroutine_result : Optional [CoroutineResult ] = None
439
441
try :
440
442
coroutine_yield = coroutine .run ()
443
+ except TailCall as tc :
444
+ coroutine_result = CoroutineResult (
445
+ coroutine_id = coroutine .id , call = tc .call , status = tc .status
446
+ )
441
447
except StopIteration as e :
442
448
coroutine_result = CoroutineResult (
443
449
coroutine_id = coroutine .id , value = e .value
@@ -450,7 +456,11 @@ def _run(self, input: Input) -> Output:
450
456
451
457
# Handle coroutines that return or raise.
452
458
if coroutine_result is not None :
453
- if coroutine_result .error is not None :
459
+ if coroutine_result .call is not None :
460
+ logger .debug (
461
+ "%s reset to %s" , coroutine , coroutine_result .call .function
462
+ )
463
+ elif coroutine_result .error is not None :
454
464
logger .debug ("%s raised %s" , coroutine , coroutine_result .error )
455
465
else :
456
466
logger .debug ("%s returned %s" , coroutine , coroutine_result .value )
@@ -463,6 +473,11 @@ def _run(self, input: Input) -> Output:
463
473
return Output .error (
464
474
Error .from_exception (coroutine_result .error )
465
475
)
476
+ if coroutine_result .call is not None :
477
+ return Output .tail_call (
478
+ tail_call = coroutine_result .call ,
479
+ status = coroutine_result .status ,
480
+ )
466
481
return Output .value (coroutine_result .value )
467
482
468
483
# Otherwise, notify the parent of the result.
0 commit comments