diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index cab87ee64b..51a7b6e6f0 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -51,11 +51,14 @@ def schedule_task(taskname, **kwargs): pass -def offload_task(taskname, *args, **kwargs): +def offload_task(taskname, force_sync=False, *args, **kwargs): """ - Create an AsyncTask. - This is different to a 'scheduled' task, - in that it only runs once! + Create an AsyncTask if workers are running. + This is different to a 'scheduled' task, + in that it only runs once! + + If workers are not running or force_sync flag + is set then the task is ran synchronously. """ try: @@ -63,10 +66,48 @@ def offload_task(taskname, *args, **kwargs): except (AppRegistryNotReady): logger.warning("Could not offload task - app registry not ready") return + import importlib + from InvenTree.status import is_worker_running - task = AsyncTask(taskname, *args, **kwargs) + if is_worker_running() and not force_sync: + # Running as asynchronous task + try: + task = AsyncTask(taskname, *args, **kwargs) + task.run() + except ImportError: + logger.warning(f"WARNING: '{taskname}' not started - Function not found") + else: + # Split path + try: + app, mod, func = taskname.split('.') + app_mod = app + '.' + mod + except ValueError: + logger.warning(f"WARNING: '{taskname}' not started - Malformed function path") + return - task.run() + # Import module from app + try: + _mod = importlib.import_module(app_mod) + except ModuleNotFoundError: + logger.warning(f"WARNING: '{taskname}' not started - No module named '{app_mod}'") + return + + # Retrieve function + try: + _func = getattr(_mod, func) + except AttributeError: + # getattr does not work for local import + _func = None + + try: + if not _func: + _func = eval(func) + except NameError: + logger.warning(f"WARNING: '{taskname}' not started - No function named '{func}'") + return + + # Workers are not running: run it as synchronous task + _func() def heartbeat(): diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 69deb8fd97..0528c6c694 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -31,8 +31,6 @@ from stock.models import StockLocation, StockItem from common.models import InvenTreeSetting, ColorTheme from users.models import check_user_role, RuleSet -import InvenTree.tasks - from .forms import DeleteForm, EditUserForm, SetPasswordForm from .forms import SettingCategorySelectForm from .helpers import str2bool @@ -827,8 +825,13 @@ class CurrencyRefreshView(RedirectView): On a POST request we will attempt to refresh the exchange rates """ - # Will block for a little bit - InvenTree.tasks.update_exchange_rates() + from InvenTree.tasks import offload_task + + # Define associated task from InvenTree.tasks list of methods + taskname = 'InvenTree.tasks.update_exchange_rates' + + # Run it + offload_task(taskname, force_sync=True) return redirect(reverse_lazy('settings'))