Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/kolibri_android/main_activity/activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def on_activity_stopped(self, activity):
# run after thsi one, so we need to keep track of the webview's
# URL before switching to the loading screen.
self._last_kolibri_path = self._get_current_kolibri_path()
self._kolibri_bus.transition("IDLE")
self._kolibri_bus.stop_services()
elif self._kolibri_bus.state != "IDLE":
logging.warning(
f"Kolibri is unable to stop because its state is '{self._kolibri_bus.state}"
Expand All @@ -116,7 +116,9 @@ def on_activity_resumed(self, activity):
if self._kolibri_bus is None:
return

if self._kolibri_bus.can_transition("START"):
if self._kolibri_bus.state == "START":
self._kolibri_bus.start_services()
elif self._kolibri_bus.can_transition("START"):
self._last_kolibri_path = None
self._kolibri_bus.transition("START")
elif self._kolibri_bus.state != "START":
Expand Down
34 changes: 33 additions & 1 deletion src/kolibri_android/main_activity/kolibri_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,37 @@
from magicbus.plugins import SimplePlugin


class PausableServicesPlugin(ServicesPlugin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._started = False
self._stopped = False

def START(self):
if not self._started:
logging.debug("PausableServicesPlugin full start'")
super().START()
self._started = True
elif self._stopped:
logging.debug("PausableServicesPlugin partial start'")
from kolibri.core.tasks.main import initialize_workers

self.worker = initialize_workers()
self._stopped = False
else:
logging.debug("PausableServicesPlugin skip start'")

def STOP(self):
super().STOP()
self._stopped = True


class KolibriAppProcessBus(BaseKolibriProcessBus):
def __init__(self, *args, enable_zeroconf=True, **kwargs):
super(KolibriAppProcessBus, self).__init__(*args, **kwargs)

ServicesPlugin(self).subscribe()
self._services = PausableServicesPlugin(self)
self._services.subscribe()

if enable_zeroconf:
ZeroConfPlugin(self, self.port).subscribe()
Expand Down Expand Up @@ -49,6 +75,12 @@ def is_kolibri_url(self, url):

return False

def stop_services(self):
self._services.STOP()

def start_services(self):
self._services.START()

Comment on lines +81 to +83
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible for an activity's onStart() callback to run multiple times in between calls to onStop(), for example if the activity is paused but not stopped. Looking at ServicesPlugin source, it appears the iceqube engine is going to be created from scratch each time the START() function runs: https://github.com/learningequality/kolibri/blob/bbd63a9c1f0371dc5009f59375c43aec26092610/kolibri/utils/server.py#L255-L267.

So, I think we should add a way to keep track of whether the services plugin has been stopped or started so we aren't doing it needlessly. Perhaps add our own PausableServicesPlugin which keeps track of that state?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback! I was able not only to skip the START when it wasn't stopped before, but also to partially start after stopped. To prevent calling schedule_ping() and schedule_vacuum() multiple times. See the fixup commit.

def can_transition(self, to_state: str) -> bool:
return (self.state, to_state) in self.transitions

Expand Down