From 8fe6e5b88a99143f78882b5062406e602a831d46 Mon Sep 17 00:00:00 2001 From: titulebolide Date: Mon, 24 Jan 2022 10:31:48 +0100 Subject: [PATCH] check properly that tg bot has stopped before stating a new instance of the bot on update --- .gitignore | 2 ++ btb_manager_telegram/__main__.py | 21 +++++++++++- btb_manager_telegram/buttons.py | 4 +-- btb_manager_telegram/handlers.py | 27 +++++++++++++--- btb_manager_telegram/utils.py | 55 +++++++++++++++++--------------- locales/en.yml | 2 +- 6 files changed, 77 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index 6e7e9cb..bf01e38 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ yarn.lock node_modules/ btbmt.pid nohup.out +_restart_kill_* +.vscode/ # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/btb_manager_telegram/__main__.py b/btb_manager_telegram/__main__.py index 7198027..008822c 100644 --- a/btb_manager_telegram/__main__.py +++ b/btb_manager_telegram/__main__.py @@ -3,9 +3,11 @@ import os import subprocess import sys +import time import colorama import i18n +import psutil import telegram import telegram.ext @@ -29,6 +31,7 @@ from btb_manager_telegram.logging import logger, tg_error_handler from btb_manager_telegram.report import make_snapshot, migrate_reports from btb_manager_telegram.utils import ( + get_restart_file_name, retreive_btb_constants, setup_coin_list, setup_i18n, @@ -97,8 +100,24 @@ def pre_run_main() -> None: "NOTE: Run the 'docker_setup.py' file before passing this flag.", ) + parser.add_argument( + "--_remove_this_arg_auto_restart_old_pid", type=str, default=None + ) + args = parser.parse_args() + if args._remove_this_arg_auto_restart_old_pid is not None: + old_pid = int(args._remove_this_arg_auto_restart_old_pid.lstrip("_remove_this_arg_")) + logger.info( + f"The new process says : Restart initied. Waiting for the old process with pid {old_pid} to terminate." + ) + restart_filename = get_restart_file_name(old_pid) + open(restart_filename, "w").close() + while psutil.pid_exists(old_pid): + time.sleep(0.1) + os.remove(restart_filename) + logger.info(f"The new process says : The old process has terminated. Starting.") + if args.docker: run_on_docker() exit(1) @@ -111,7 +130,7 @@ def pre_run_main() -> None: settings.START_TRADE_BOT = args.start_trade_bot settings.CURRENCY = args.currency settings.OER_KEY = args.oer_key - settings.RAW_ARGS = " ".join(sys.argv[1:]) + settings.RAW_ARGS = [i for i in sys.argv[1:] if "_remove_this_arg_" not in i] if settings.CURRENCY not in ("USD", "EUR") and ( settings.OER_KEY is None or settings.OER_KEY == "" diff --git a/btb_manager_telegram/buttons.py b/btb_manager_telegram/buttons.py index b26ba02..b4d4290 100644 --- a/btb_manager_telegram/buttons.py +++ b/btb_manager_telegram/buttons.py @@ -614,10 +614,10 @@ def update_tg_bot(): message = i18n.t("update.tgb.up_to_date") upd = False - to_update = is_tg_bot_update_available() + to_update, cur_vers, rem_vers = is_tg_bot_update_available() if to_update is not None: if to_update: - message = f"{i18n.t('update.tgb.available')}\n" f"{i18n.t('update.now')}" + message = f"{i18n.t('update.tgb.available', current_version=cur_vers, remote_version=rem_vers)}\n{i18n.t('update.now')}" upd = True else: message = i18n.t("update.tgb.error") diff --git a/btb_manager_telegram/handlers.py b/btb_manager_telegram/handlers.py index 80101ff..61b5dc1 100644 --- a/btb_manager_telegram/handlers.py +++ b/btb_manager_telegram/handlers.py @@ -5,6 +5,7 @@ import sqlite3 import subprocess import sys +import time import traceback import i18n @@ -42,6 +43,7 @@ from btb_manager_telegram.utils import ( find_and_kill_binance_trade_bot_process, get_custom_scripts_keyboard, + get_restart_file_name, kill_btb_manager_telegram_process, ) @@ -453,14 +455,29 @@ def update_tg_bot(update, _): ) try: manager_python_path = sys.executable - subprocess.call( - f"git pull && {manager_python_path} -m pip install -r requirements.txt --upgrade && " - f"{manager_python_path} -m btb_manager_telegram {settings.RAW_ARGS} &", + subprocess.run( + f"git pull" + f" && git checkout $(git describe --abbrev=0 --tags)" + f" && {manager_python_path} -m pip install -r requirements.txt --upgrade" + f" && {manager_python_path} -m btb_manager_telegram {' '.join(settings.RAW_ARGS)} --_remove_this_arg_auto_restart_old_pid _remove_this_arg_{os.getpid()} &", shell=True, + check=True ) - kill_btb_manager_telegram_process() + restart_filename = get_restart_file_name(os.getpid()) + max_attempts = 200 + attempts = 0 + while (not os.path.isfile(restart_filename)) and (attempts < max_attempts): + # waiting for the tg bot to prove it is alive + attempts += 1 + time.sleep(0.1) + if os.path.isfile(restart_filename): + logger.info("The old process says : The new process has started. Exiting.") + kill_btb_manager_telegram_process() + else: + logger.error(f"Unable to restart the telegram bot") + except Exception as e: - logger.error(f"❌ Unable to update BTB Manager Telegram: {e}", exc_info=True) + logger.error(f"Unable to update BTB Manager Telegram: {e}", exc_info=True) message = i18n.t("update.tgb.error") reply_text_escape_fun( message, reply_markup=reply_markup, parse_mode="MarkdownV2" diff --git a/btb_manager_telegram/utils.py b/btb_manager_telegram/utils.py index ddbbb99..91cde1a 100644 --- a/btb_manager_telegram/utils.py +++ b/btb_manager_telegram/utils.py @@ -168,7 +168,7 @@ def kill_btb_manager_telegram_process(): logger.info(f"ERROR: {e}") -def is_tg_bot_update_available(): +def is_btb_bot_update_available(): try: proc = subprocess.Popen( ["bash", "-c", "git remote update origin && git status -uno"], @@ -182,38 +182,35 @@ def is_tg_bot_update_available(): return re -def is_btb_bot_update_available(): - try: - subprocess.run(["git", "remote", "update", "origin"]) - current_version = ( - subprocess.check_output(["git", "describe", "--abbrev=0", "--tags"]) - .decode() - .rstrip("\n") - ) - remote_version = ( - subprocess.check_output( - ["git", "describe", "--abbrev=0", "--tags", "origin/main"] - ) - .decode() - .rstrip("\n") +def is_tg_bot_update_available(): + subprocess.run(["git", "remote", "update", "origin"], check=True) + current_version = ( + subprocess.check_output(["git", "describe", "--abbrev=0", "--tags"]) + .decode() + .rstrip("\n") + ) + remote_version = ( + subprocess.check_output( + ["git", "describe", "--abbrev=0", "--tags", "origin/main"] ) - re = current_version != remote_version - except Exception as e: - logger.error(e, exc_info=True) - re = None - return re + .decode() + .rstrip("\n") + ) + re = current_version != remote_version + return re, current_version, remote_version def update_checker(): logger.info("Checking for updates.") if settings.TG_UPDATE_BROADCASTED_BEFORE is False: - if is_tg_bot_update_available(): - logger.info("BTB Manager Telegram update found.") - message = ( - f"{i18n.t('update.tgb.available')}\n\n" - f"{i18n.t('update.tgb.instruction')}" + to_update, cur_vers, rem_vers = is_tg_bot_update_available() + if to_update: + logger.info( + f"BTB Manager Telegram update found. ({cur_vers} -> {rem_vers})" ) + message = f"{i18n.t('update.tgb.available', current_version=cur_vers, remote_version=rem_vers)}\n\n{i18n.t('update.tgb.instruction')}" + print(message) settings.TG_UPDATE_BROADCASTED_BEFORE = True settings.CHAT.send_message(escape_tg(message), parse_mode="MarkdownV2") scheduler.enter( @@ -286,3 +283,11 @@ def get_custom_scripts_keyboard(): keyboard.append([i18n.t("keyboard.cancel")]) return keyboard, custom_script_exist, message + + +def get_restart_file_name(old_pid): + """ + returns the name of the file that has to be created + by the new process to inform the old process of the btb to stop + """ + return f"_restart_kill_{old_pid}" diff --git a/locales/en.yml b/locales/en.yml index 4b7225b..ace16e6 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -184,7 +184,7 @@ update: error: "Unable to update BTB Manager Telegram" not_updated: "BTB Manager Telegram was *not* updated." up_to_date: "Your BTB Manager Telegram installation is already up to date." - available: "An update for BTB Manager Telegram is available." + available: "Your telegram manager is currently on version %{current_version}, and version %{remote_version} is available." instruction: "Please update by going to *🛠 Maintenance* and pressing the *⬆ Update Telegram Bot* button." btb: