File size: 2,702 Bytes
321925b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
"""Hermes Daemon — 后台训练守护进程."""

import time
import signal
import sys
from pathlib import Path

# Fix Unicode display on Windows (GBK terminal)
if sys.platform == "win32":
    sys.stdout.reconfigure(encoding="utf-8", errors="replace")
    sys.stderr.reconfigure(encoding="utf-8", errors="replace")
from hermes_core.types import HERMES_DATA_DIR
from hermes_core.db import init_db, get_scopes_needing_training, get_active_records
from hermes_core.scheduler import check_idle, get_training_queue, process_queue
from hermes_core.config import get_config


running = True


def _signal_handler(signum, frame):
    global running
    running = False
    print("\nShutting down daemon gracefully...")


def _get_all_users() -> list[str]:
    """扫描所有有数据的用户。"""
    users_dir = Path(get_config().data_dir) / "users"
    if not users_dir.exists():
        return []
    return [d.name for d in users_dir.iterdir() if d.is_dir()]


def main():
    """Daemon 主循环。从配置文件读取扫描间隔等参数。"""
    config = get_config()
    interval = config.scan_interval_seconds

    signal.signal(signal.SIGINT, _signal_handler)
    signal.signal(signal.SIGTERM, _signal_handler)

    print(f"Hermes Daemon v0.1.0 started")
    print(f"  Scan interval: {interval}s")
    print(f"  Data dir: {config.data_dir}")
    print(f"  CPU threshold: {config.cpu_idle_threshold}")
    print(f"  Log: {config.log_file}")

    while running:
        users = _get_all_users()
        for user_id in users:
            if not running:
                break
            try:
                conn = init_db(user_id)
                scopes_needing = get_scopes_needing_training(conn)
                conn.close()

                if not scopes_needing:
                    continue

                queue = get_training_queue(user_id)
                if not queue:
                    continue

                if check_idle(config.cpu_idle_threshold, config.gpu_idle_threshold):
                    print(f"[{time.strftime('%H:%M:%S')}] Idle detected. "
                          f"Training {queue[0]['scope_id']} for user {user_id}")
                    count = process_queue(user_id)
                    if count > 0:
                        print(f"[{time.strftime('%H:%M:%S')}] "
                              f"Training complete for {queue[0]['scope_id']}")
            except Exception as e:
                print(f"[{time.strftime('%H:%M:%S')}] Error processing user {user_id}: {e}")

        for _ in range(interval):
            if not running:
                break
            time.sleep(1)

    print("Hermes Daemon stopped.")


if __name__ == "__main__":
    main()