fix(shadow): 多账户worker不抢全局solo锁——根因实锤:__main__对--account N也走~/.sanguo_shadow_desk.lock全局锁,全机只放行一个影子worker(谁先抢到谁活),supervisor多账户并存时其余全部'锁占用'rc=0优雅退出→每60s重拉秒退循环;VPS实录40/41反复退出+42抢到锁独活(shadow_41.log一击定位);单账户时代从未暴露,2026-08-16用户建三影子账户即炸。修:--account分支跳过全局锁直进run_shadow(同账户防重复由bullet_trade runtime/shadow_{aid}实例锁+supervisor children表兜底);solo模式(无--account)维持全局锁防双开;+3路由测试(account跳锁/solo持锁/auto不碰柜台);936绿 [vps]
CI/CD / test (push) Successful in 8s
CI/CD / nas-deploy (push) Successful in 25s
CI/CD / nas-verify (push) Successful in 13s

This commit is contained in:
2026-08-16 18:51:07 +08:00
parent 9bb4bda8a4
commit 3f6b681d0f
2 changed files with 65 additions and 0 deletions
+9
View File
@@ -60,6 +60,15 @@ def main() -> int:
run_auto_supervisor()
return 0
if "--account" in sys.argv:
# 多账户 worker 不抢全局 solo 锁:全局锁全机只放行一个 worker,supervisor
# 多账户并存时其余全部"锁占用"优雅退出(VPS 2026-08-16 实录 40/41 反复
# rc=0,单账户时代从未暴露)。同账户防重复由 bullet_trade
# runtime/shadow_{aid} 实例锁兜底,supervisor children 表保证一账户一进程。
from .runner import run_shadow
run_shadow()
return 0
lock = _acquire_lock()
if lock is None:
print("影子柜台已在运行(锁占用),本次启动退出。", flush=True)
+56
View File
@@ -0,0 +1,56 @@
"""影子柜台 CLI 路由:--account worker 不抢全局 solo 锁(多账户并存的前提)。"""
import sys
import pytest
def _run_main(monkeypatch, argv):
from sanguo_trader.shadow import __main__ as m
calls = {"lock": 0, "shadow": 0, "auto": 0}
def _no_lock():
calls["lock"] += 1
return object()
def _shadow(*a, **k):
calls["shadow"] += 1
def _auto(*a, **k):
calls["auto"] += 1
import sanguo_trader.shadow.runner as runner_mod
import sanguo_trader.shadow.supervisor as sup
monkeypatch.setattr(m, "_acquire_lock", _no_lock)
# main() 内 lazy import:patch 源模块而非 __main__
monkeypatch.setattr(runner_mod, "run_shadow", _shadow)
monkeypatch.setattr(sup, "run_auto_supervisor", _auto)
monkeypatch.setattr(sys, "argv", ["prog", *argv])
rc = m.main()
return rc, calls
def test_account_worker_skips_global_lock(monkeypatch):
"""--account N:多账户 worker 不碰全局锁(VPS 实录 40/41「锁占用」循环退出)。"""
rc, calls = _run_main(monkeypatch, ["--account", "41"])
assert rc == 0
assert calls["shadow"] == 1
assert calls["lock"] == 0 # 关键:不抢全局 solo 锁
def test_solo_mode_still_locks(monkeypatch):
"""无 --account 的 solo 模式维持全局锁(防双开)。"""
rc, calls = _run_main(monkeypatch, [])
assert rc == 0
assert calls["shadow"] == 1
assert calls["lock"] == 1
def test_auto_mode_no_lock_no_shadow(monkeypatch):
"""--auto 主管:既不抢锁也不起柜台。"""
rc, calls = _run_main(monkeypatch, ["--auto"])
assert rc == 0
assert calls["auto"] == 1
assert calls["lock"] == 0
assert calls["shadow"] == 0