From 6cc71aa5d764c8d2c098db61eae2cfc33cdd89c1 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 4 Apr 2025 15:27:57 -0700 Subject: [PATCH] app: During startup, run post-init operation in background - This allows for the service to become "ready" and serving web connection sooner. - If some operations such as obtaining certificates and domain configurations are happening, these can be shown as operations with UI notifications. Tests: - Running 'freedombox-develop --setup' works. 'App initialization completed' message is printed before 'Running setup...' message. Process exits successfully. - Running 'freedombox-develop --setup-no-install' works. 'App initialization completed' message is printed before 'Running setup...' message. Process exits successfully. - Running 'freedombox-develop' works. 'App initialization completed' message is printed before 'Running regular setup' and 'Setup finished'. Cherrypy starts listening before 'App initialization completed' message. - Running a fresh VM setup works. Signed-off-by: Sunil Mohan Adapa Reviewed-by: James Valleroy --- plinth/__main__.py | 14 +++++++++++--- plinth/setup.py | 23 ++++++----------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/plinth/__main__.py b/plinth/__main__.py index 3fa050e1c..fba9fea58 100644 --- a/plinth/__main__.py +++ b/plinth/__main__.py @@ -4,6 +4,7 @@ import argparse import logging import sys +import threading from . import __version__ from . import app as app_module @@ -95,6 +96,13 @@ def on_web_server_stop(): glib.stop() +def run_post_init_and_setup(): + """Run post-init operations on the apps and setup operations.""" + app_module.apps_post_init() + frontpage.add_custom_shortcuts() + setup.run_setup_on_startup() # Long running, retrying + + def main(): """Initialize and start the application""" arguments = parse_arguments() @@ -134,16 +142,16 @@ def main(): module_loader.load_modules() app_module.apps_init() - app_module.apps_post_init() - frontpage.add_custom_shortcuts() if arguments.setup is not False: + app_module.apps_post_init() run_setup_and_exit(arguments.setup, allow_install=True) if arguments.setup_no_install is not False: + app_module.apps_post_init() run_setup_and_exit(arguments.setup_no_install, allow_install=False) - setup.run_setup_in_background() + threading.Thread(target=run_post_init_and_setup).start() glib.run() diff --git a/plinth/setup.py b/plinth/setup.py index e66fe3aac..a7fcef3e6 100644 --- a/plinth/setup.py +++ b/plinth/setup.py @@ -26,7 +26,6 @@ from .privileged import packages as packages_privileged logger = logging.getLogger(__name__) -_is_first_setup = False is_first_setup_running = False _is_shutting_down = False @@ -273,18 +272,15 @@ def list_dependencies(app_ids=None, essential=False): print(package_expression) -def run_setup_in_background(): - """Run setup in a background thread.""" - _set_is_first_setup() - threading.Thread(target=_run_setup_on_startup).start() - - -def _run_setup_on_startup(): +def run_setup_on_startup(): """Run setup with retry till it succeeds.""" + is_first_setup = any((app for app in app_module.App.list() + if app.info.is_essential and app.needs_setup())) + sleep_time = 10 while True: try: - if _is_first_setup: + if is_first_setup: logger.info('Running first setup.') _run_first_setup() break @@ -299,7 +295,7 @@ def _run_setup_on_startup(): if _is_shutting_down: break - logger.info('Setup thread finished.') + logger.info('Setup finished.') def _run_first_setup(): @@ -337,13 +333,6 @@ def _get_apps_for_regular_setup(): ] -def _set_is_first_setup(): - """Set whether all essential apps have been setup at least once.""" - global _is_first_setup - _is_first_setup = any((app for app in app_module.App.list() - if app.info.is_essential and app.needs_setup())) - - def run_setup_on_apps(app_ids, allow_install=True): """Run setup on the given list of apps.