@@ -343,7 +343,7 @@ def __init__(
343343 self ._in_task_output_backpressure = False
344344 self ._estimated_num_output_bundles = None
345345 self ._estimated_output_num_rows = None
346- self ._execution_finished = False
346+ self ._is_execution_marked_finished = False
347347 # The LogicalOperator(s) which were translated to create this PhysicalOperator.
348348 # Set via `PhysicalOperator.set_logical_operators()`.
349349 self ._logical_operators : List [LogicalOperator ] = []
@@ -401,48 +401,51 @@ def override_target_max_block_size(self, target_max_block_size: Optional[int]):
401401
402402 def mark_execution_finished (self ):
403403 """Manually mark that this operator has finished execution."""
404- self ._execution_finished = True
404+ self ._is_execution_marked_finished = True
405405
406- def execution_finished (self ) -> bool :
406+ def has_execution_finished (self ) -> bool :
407407 """Return True when this operator has finished execution.
408408
409409 The outputs may or may not have been taken.
410410 """
411- return self ._execution_finished
411+ from ..operators .base_physical_operator import InternalQueueOperatorMixin
412+
413+ internal_input_queue_num_blocks = 0
414+ if isinstance (self , InternalQueueOperatorMixin ):
415+ internal_input_queue_num_blocks = self .internal_input_queue_num_blocks ()
416+
417+ # NOTE: Execution is considered finished if
418+ # - The operator was explicitly marked finished OR
419+ # - The following auto-completion conditions are met
420+ # - All input blocks have been ingested
421+ # - Internal queue is empty
422+ # - There are no active or pending tasks
423+
424+ return self ._is_execution_marked_finished or (
425+ self ._inputs_complete
426+ and self .num_active_tasks () == 0
427+ and internal_input_queue_num_blocks == 0
428+ )
412429
413430 def completed (self ) -> bool :
414431 """Returns whether this operator has been fully completed.
415432
416433 An operator is completed iff:
417- * The operator has finished execution (i.e., `execution_finished ()` is True).
434+ * The operator has finished execution (i.e., `has_execution_finished ()` is True).
418435 * All outputs have been taken (i.e., `has_next()` is False) from it.
419436 """
420437 from ..operators .base_physical_operator import InternalQueueOperatorMixin
421438
422- internal_input_queue_num_blocks = 0
423439 internal_output_queue_num_blocks = 0
424440 if isinstance (self , InternalQueueOperatorMixin ):
425- internal_input_queue_num_blocks = self .internal_input_queue_num_blocks ()
426441 internal_output_queue_num_blocks = self .internal_output_queue_num_blocks ()
427442
428- if not self ._execution_finished :
429- if (
430- self ._inputs_complete
431- and internal_input_queue_num_blocks == 0
432- and self .num_active_tasks () == 0
433- ):
434- # NOTE: Operator is considered completed iff
435- # - All input blocks have been ingested
436- # - Internal queue is empty
437- # - There are no active or pending tasks
438- self ._execution_finished = True
439-
440443 # NOTE: We check for (internal_output_queue_size == 0) and
441444 # (not self.has_next()) because _OrderedOutputQueue can
442445 # return False for self.has_next(), but have a non-empty queue size.
443446 # Draining the internal output queue is important to free object refs.
444447 return (
445- self ._execution_finished
448+ self .has_execution_finished ()
446449 and not self .has_next ()
447450 and internal_output_queue_num_blocks == 0
448451 )
0 commit comments