Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publisher: Fix stop of publishing #847

Merged
merged 10 commits into from
Aug 26, 2024
19 changes: 13 additions & 6 deletions client/ayon_core/tools/publisher/control_qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,8 @@ def stop(self):
self._timer.stop()

def clear(self):
if self._timer.isActive():
self._timer.stop()
self._items_to_process = collections.deque()
self.stop()


class QtPublisherController(PublisherController):
Expand All @@ -77,21 +76,27 @@ def __init__(self, *args, **kwargs):
self.register_event_callback(
"publish.process.stopped", self._qt_on_publish_stop
)
self._item_process_in_loop = False

def reset(self):
self._main_thread_processor.clear()
self._item_process_in_loop = False
super().reset()

def _start_publish(self, up_validation):
self._publish_model.set_publish_up_validation(up_validation)
self._publish_model.start_publish(wait=False)
self._process_main_thread_item(
MainThreadItem(self._next_publish_item_process)
)
if not self._item_process_in_loop:
self._process_main_thread_item(
MainThreadItem(self._next_publish_item_process)
)

def _next_publish_item_process(self):
if not self._publish_model.is_running():
self._item_process_in_loop = False
return

self._item_process_in_loop = True
func = self._publish_model.get_next_process_func()
self._process_main_thread_item(MainThreadItem(func))
self._process_main_thread_item(
Expand All @@ -105,4 +110,6 @@ def _qt_on_publish_start(self):
self._main_thread_processor.start()

def _qt_on_publish_stop(self):
self._main_thread_processor.stop()
self._process_main_thread_item(
MainThreadItem(self._main_thread_processor.stop)
)
72 changes: 41 additions & 31 deletions client/ayon_core/tools/publisher/models/publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,9 @@ def __init__(self, controller: AbstractPublisherBackend):
)

# Plugin iterator
self._main_thread_iter: Iterable[partial] = []
self._main_thread_iter: collections.abc.Generator[partial] = (
self._default_iterator()
)

def reset(self):
create_context = self._controller.get_create_context()
Expand Down Expand Up @@ -907,29 +909,30 @@ def start_publish(self, wait: Optional[bool] = True):
func()

def get_next_process_func(self) -> partial:
# Raise error if this function is called when publishing
# is not running
if not self._publish_is_running:
raise ValueError("Publish is not running")

# Validations of progress before using iterator
# - same conditions may be inside iterator but they may be used
# only in specific cases (e.g. when it happens for a first time)
# Any unexpected error happened
# - everything should stop
if self._publish_has_crashed:
return partial(self.stop_publish)

# Stop if validation is over and validation errors happened
# or publishing should stop at validation
if (
self._main_thread_iter is None
# There are validation errors and validation is passed
# - can't do any progree
or (
self._publish_has_validated
and self._publish_has_validation_errors
self._publish_has_validated
and (
self._publish_has_validation_errors
or self._publish_up_validation
)
# Any unexpected error happened
# - everything should stop
or self._publish_has_crashed
):
item = partial(self.stop_publish)
return partial(self.stop_publish)

# Everything is ok so try to get new processing item
else:
item = next(self._main_thread_iter)

return item
return next(self._main_thread_iter)

def stop_publish(self):
if self._publish_is_running:
Expand Down Expand Up @@ -1082,6 +1085,19 @@ def _set_publish_error_msg(self, value: Optional[str]):
{"value": value}
)

def _default_iterator(self):
"""Iterator used on initialization.

Should be replaced by real iterator when 'reset' is called.

Returns:
collections.abc.Generator[partial]: Generator with partial
functions that should be called in main thread.

"""
while True:
yield partial(self.stop_publish)

def _start_publish(self):
"""Start or continue in publishing."""
if self._publish_is_running:
Expand Down Expand Up @@ -1113,22 +1129,16 @@ def _publish_iterator(self) -> Iterable[partial]:
self._publish_progress = idx

# Check if plugin is over validation order
if not self._publish_has_validated:
self._set_has_validated(
plugin.order >= self._validation_order
)

# Stop if plugin is over validation order and process
# should process up to validation.
if self._publish_up_validation and self._publish_has_validated:
yield partial(self.stop_publish)

# Stop if validation is over and validation errors happened
if (
self._publish_has_validated
and self.has_validation_errors()
not self._publish_has_validated
and plugin.order >= self._validation_order
):
yield partial(self.stop_publish)
self._set_has_validated(True)
if (
self._publish_up_validation
or self._publish_has_validation_errors
):
yield partial(self.stop_publish)

# Add plugin to publish report
self._publish_report.add_plugin_iter(
Expand Down