1
0
mirror of https://github.com/0O0o0oOoO00/Alas.git synced 2026-05-14 11:49:26 +08:00

add: add instance watcher support

This commit is contained in:
0O0o0oOoO00
2025-09-13 14:41:52 +08:00
parent 8d7f718285
commit 17482d44e1
2 changed files with 202 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
import threading
import time
from dataclasses import dataclass
from typing import Dict
from module.config.config import AzurLaneConfig
from module.counter import MaxCounter
from module.notify import handle_notify
from module.webui.process_manager import ProcessManager
@dataclass
class InstanceSetting:
counter: MaxCounter
enable_notify: bool
notify_config: str
class InstanceWatcher:
instance = None
def __init__(self):
self.watcher: threading.Thread = None
self.instances: Dict[str, InstanceSetting] = dict()
def start(self):
if self.watcher is not None:
if self.watcher.is_alive():
return
self.watcher = threading.Thread(target=self.watcher_thread, daemon=True)
self.watcher.start()
def check_instances(self):
ins_has_triggered = []
for name, setting in self.instances.items():
ins = ProcessManager.get_manager(name)
if not ins.alive:
if setting.counter.count_once(throw=False):
ins.start("alas")
if setting.enable_notify:
handle_notify(
setting.notify_config,
title=f"Alas <{ins.config_name}> instance auto restarted",
content=f"Critical error occurred, instance restarted",
)
else:
ins_has_triggered.append(name)
handle_notify(
setting.notify_config,
title=f"Alas <{ins.config_name}> instance restarted too many times",
content=f"Too many critical error occurred, instance restarted too many times",
)
for i in ins_has_triggered:
self.remove_instance(i)
def try_add_instance(self, name):
config = AzurLaneConfig(name)
full_config = config.full_config
if full_config.Restart_InstanceRestart_Enable:
setting = InstanceSetting(
counter=MaxCounter(full_config.Restart_InstanceRestart_MaxRetryTimes),
enable_notify=full_config.Restart_InstanceRestart_Notify,
notify_config=full_config.Alas_Error_OnePushConfig
)
self.instances[name] = setting
def remove_instance(self, name):
try:
self.instances.pop(name)
except Exception:
...
def watcher_thread(self):
while 1:
time.sleep(60)
try:
self.check_instances()
except Exception:
...
@staticmethod
def get_instance() -> "InstanceWatcher":
if InstanceWatcher.instance is None:
InstanceWatcher.instance = InstanceWatcher()
return InstanceWatcher.instance

View File

@@ -1525,3 +1525,119 @@ def app():
)
return app
from module.instance_watcher import InstanceWatcher
class AlasGUI(AlasGUI):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.instance_watcher = InstanceWatcher.get_instance()
def on_start_on(self):
self.instance_watcher.remove_instance(self.alas.config_name)
self.alas.stop()
def on_start_off(self):
self.alas.start(None, updater.event)
self.instance_watcher.try_add_instance(self.alas.config_name)
@use_scope("content", clear=True)
def alas_overview(self) -> None:
self.init_menu(name="Overview")
self.set_title(t(f"Gui.MenuAlas.Overview"))
put_scope("overview", [put_scope("schedulers"), put_scope("logs")])
with use_scope("schedulers"):
put_scope(
"scheduler-bar",
[
put_text(t("Gui.Overview.Scheduler")).style(
"font-size: 1.25rem; margin: auto .5rem auto;"
),
put_scope("scheduler_btn"),
],
)
put_scope(
"running",
[
put_text(t("Gui.Overview.Running")),
put_html('<hr class="hr-group">'),
put_scope("running_tasks"),
],
)
put_scope(
"pending",
[
put_text(t("Gui.Overview.Pending")),
put_html('<hr class="hr-group">'),
put_scope("pending_tasks"),
],
)
put_scope(
"waiting",
[
put_text(t("Gui.Overview.Waiting")),
put_html('<hr class="hr-group">'),
put_scope("waiting_tasks"),
],
)
switch_scheduler = BinarySwitchButton(
label_on=t("Gui.Button.Stop"),
label_off=t("Gui.Button.Start"),
onclick_on=self.on_start_on,
onclick_off=self.on_start_off,
get_state=lambda: self.alas.alive,
color_on="off",
color_off="on",
scope="scheduler_btn",
)
log = RichLog("log")
with use_scope("logs"):
put_scope(
"log-bar",
[
put_text(t("Gui.Overview.Log")).style(
"font-size: 1.25rem; margin: auto .5rem auto;"
),
put_scope(
"log-bar-btns",
[
put_scope("log_scroll_btn"),
],
),
],
)
put_scope("log", [put_html("")])
log.console.width = log.get_width()
switch_log_scroll = BinarySwitchButton(
label_on=t("Gui.Button.ScrollON"),
label_off=t("Gui.Button.ScrollOFF"),
onclick_on=lambda: log.set_scroll(False),
onclick_off=lambda: log.set_scroll(True),
get_state=lambda: log.keep_bottom,
color_on="on",
color_off="off",
scope="log_scroll_btn",
)
self.task_handler.add(switch_scheduler.g(), 1, True)
self.task_handler.add(switch_log_scroll.g(), 1, True)
self.task_handler.add(self.alas_update_overview_task, 10, True)
self.task_handler.add(log.put_log(self.alas), 0.25, True)
old_app = app
def app():
ret = old_app()
InstanceWatcher.get_instance().start()
return ret