feat: refresh material names in background every two days

This commit is contained in:
ar51
2026-10-09 10:44:03 +08:00
parent cf31549415
commit 512e434a2f
11 changed files with 406 additions and 37 deletions

View File

@@ -0,0 +1,67 @@
"""Install the native macOS background material-name refresher."""
from __future__ import annotations
import argparse
import os
import plistlib
import subprocess
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
LABEL = "com.am516.material-name-refresh"
def launch_agent(project: Path, python: Path, log_dir: Path, client: Path | None = None) -> dict:
command = [str(python), str(project / "capabilities/am516-delivery-prediction/scripts/refresh_material_names.py"), "--due", "--interval-hours", "48"]
if client is not None:
command.extend(["--kingdee-client", str(client)])
return {
"Label": LABEL, "ProgramArguments": command, "WorkingDirectory": str(project),
"RunAtLoad": True, "StartInterval": 3600, "ProcessType": "Background",
"EnvironmentVariables": {"PYTHONDONTWRITEBYTECODE": "1", "PYTHONUNBUFFERED": "1"},
"StandardOutPath": str(log_dir / "material_name_refresh.log"),
"StandardErrorPath": str(log_dir / "material_name_refresh.error.log"),
}
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("action", choices=("install", "status", "uninstall", "preview"))
parser.add_argument("--python", type=Path, default=Path(sys.executable))
parser.add_argument("--kingdee-client", type=Path)
args = parser.parse_args()
if args.kingdee_client is not None:
args.kingdee_client = args.kingdee_client.resolve()
destination = Path.home() / "Library/LaunchAgents" / f"{LABEL}.plist"
logs = Path.home() / "Library/Logs/AM516_Feishu_Bot"
domain = f"gui/{os.getuid()}"
service = f"{domain}/{LABEL}"
if args.action == "preview":
print(plistlib.dumps(launch_agent(PROJECT_ROOT, args.python.resolve(), logs, args.kingdee_client)).decode())
return 0
if args.action == "status":
return subprocess.run(["launchctl", "print", service]).returncode
if args.action in ("install", "uninstall"):
exists = subprocess.run(["launchctl", "print", service], capture_output=True).returncode == 0
if exists:
subprocess.run(["launchctl", "bootout", service], check=True)
if args.action == "uninstall":
destination.unlink(missing_ok=True)
print("已移除物料名称后台刷新服务。")
return 0
destination.parent.mkdir(parents=True, exist_ok=True)
logs.mkdir(parents=True, exist_ok=True)
(PROJECT_ROOT / "logs").mkdir(exist_ok=True)
with destination.open("wb") as handle:
plistlib.dump(launch_agent(PROJECT_ROOT, args.python.resolve(), logs, args.kingdee_client), handle)
subprocess.run(["launchctl", "bootstrap", domain, str(destination)], check=True)
print("已安装物料名称后台刷新:每小时检查,成功刷新后间隔48小时再次查询 ERP。")
print(f"服务:{service}")
return 0
if __name__ == "__main__":
raise SystemExit(main())