summaryrefslogtreecommitdiff
path: root/scripts/m3r-master.sh
blob: d4f18faa7733fe5438f7fea2a0f8cdf5bd3a59db (plain)
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
#!/usr/bin/env bash
# M3R 缩尺批验 MasterProcess 包装器(systemd --user 单元 ExecStart 指向本脚本)。
#
# 职责:
#   * 在 <M3R_DIR> 落 state.json(pid/unit/log/commit/workers/worlds/days/起止/exit);
#   * 以 2>&1 运行 Headless Release 批处理 `--batch <worlds> <days>`,逐世界流式;
#   * 进程退出即写回 ended_at 与退出码,并把真实退出码回传给 systemd。
#
# 环境变量(由 unit 注入):
#   M3R_REPO    仓库根(绝对路径)
#   M3R_DIR     本次运行证据目录(绝对路径,state.json 落此)
#   M3R_COMMIT  期望 commit 短哈希(写入 state.json)
#   M3R_WORLDS  世界数(默认 50)
#   M3R_DAYS    模拟天数(默认 15)
#   LV_BATCH_WORKERS  并行 worker 数(默认 12)
#   M3R_LOG     验收日志路径(只写入 state.json 作为记录,实际重定向由 unit 负责)
set -u

REPO="${M3R_REPO:?M3R_REPO required}"
DIR="${M3R_DIR:?M3R_DIR required}"
COMMIT="${M3R_COMMIT:?M3R_COMMIT required}"
WORLDS="${M3R_WORLDS:-50}"
DAYS="${M3R_DAYS:-15}"
WORKERS="${LV_BATCH_WORKERS:-12}"
LOG="${M3R_LOG:-$REPO/artifacts/m3r-acceptance/acceptance.log}"
UNIT="living-village-m3r.service"
DLL="$REPO/src/LivingVillage.Headless/bin/Release/net8.0/LivingVillage.Headless.dll"

mkdir -p "$DIR"
if [ ! -f "$DLL" ]; then
    echo "[m3r] FATAL missing build: $DLL" >&2
    exit 90
fi

STARTED="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "$$" > "$DIR/pid"
echo "[m3r] start unit=$UNIT pid=$$ commit=$COMMIT workers=$WORKERS worlds=$WORLDS days=$DAYS started_at=$STARTED"

python3 - "$DIR/state.json" "$UNIT" "$COMMIT" "$WORKERS" "$WORLDS" "$DAYS" "$LOG" "$STARTED" "$$" <<'PY'
import json, sys
out, unit, commit, workers, worlds, days, log, started, pid = sys.argv[1:10]
state = {
    "pid": int(pid),
    "unit": unit,
    "log": log,
    "commit": commit,
    "workers": int(workers),
    "worlds": int(worlds),
    "days": int(days),
    "started_at": started,
    "ended_at": None,
    "exit": None,
}
with open(out, "w", encoding="utf-8") as fh:
    json.dump(state, fh, ensure_ascii=False, indent=2, sort_keys=True)
    fh.write("\n")
PY

export LV_BATCH_WORKERS="$WORKERS"
( exec dotnet "$DLL" --batch "$WORLDS" "$DAYS" 2>&1 )
CODE=$?

ENDED="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "[m3r] end pid=$$ exit=$CODE ended_at=$ENDED"

python3 - "$DIR/state.json" "$CODE" "$ENDED" <<'PY'
import json, sys
path, code, ended = sys.argv[1:4]
with open(path, encoding="utf-8") as fh:
    state = json.load(fh)
state["ended_at"] = ended
state["exit"] = int(code)
with open(path, "w", encoding="utf-8") as fh:
    json.dump(state, fh, ensure_ascii=False, indent=2, sort_keys=True)
    fh.write("\n")
PY

exit "$CODE"