fix: 自动存档几乎永不触发的真 bug——把 dirty 和 unsaved 拆开
顺着验收网页修复时发现:default 牧场根本没写进库,内存里每次 重启都是新档。根因是 session.dirty 一个标志位伺二主: * Publisher 推送循环每 ~250ms 就把 dirty 清掉(无人在线时直接清, "没人在看就不做序列化,省 CPU"); * autosave() 每 60s 才看一眼 dirty。 dirty=True 的窗口只有约 250ms,自动存档撞上它的概率约 0.4%—— 等于永不存盘。进度只在手动存档/优雅停机时落盘,进程被强杀全丢。 修法:新增 session.unsaved 专管「有变化没落盘」,_on_change / load / touch / advance_day 置位,只有成功的 save() 清位;autosave() 改看 unsaved;dirty 继续只管推送节流,hub.py 的推送循环一字未动。 两只旧测试直接操纵 dirty 驱动 autosave,固化了被修掉的耦合,改成 unsaved 表达意图;新增回归测试:推送循环清了 dirty 也要照常落盘、 没有新变化不重复写库。 真机验证:0 客户端在线纯 HTTP 种一块地,70 秒内库行更新(金币 120→112,种子钱都对得上)。515 项测试 OK。
This commit is contained in:
1 parent
305ef0dcbe
commit
ea346be484
2 files changed
+38
-7
No files matched your search
+22
-5
@@ -216,6 +216,23 @@ class FarmSessionTestCase(unittest.TestCase):
|
||||
self.assertEqual(reopened.engine.state.gold, 777)
|
||||
self.assertIn("第 9 天", reopened.load_message)
|
||||
|
||||
def test_autosave_survives_the_push_loop_clearing_dirty(self):
|
||||
"""回归:dirty 是推送节流用的,Publisher ~250ms 就清一次;自动存档
|
||||
如果也看 dirty,就等于永不存盘(进程被强杀进度全丢)。它必须看
|
||||
只有成功的 save() 才清的 unsaved。"""
|
||||
session = FarmSession("alice", self.dir, 2400.0)
|
||||
session.touch()
|
||||
session.dirty = False # 模拟 Publisher 清推送标记
|
||||
self.assertTrue(session.autosave(), "推送循环清了 dirty 也要照常落盘")
|
||||
reopened = FarmSession("alice", self.dir, 2400.0)
|
||||
self.assertIn("已载入存档", reopened.load_message)
|
||||
|
||||
def test_autosave_skips_when_nothing_changed_since_last_save(self):
|
||||
session = FarmSession("alice", self.dir, 2400.0)
|
||||
session.touch()
|
||||
self.assertTrue(session.autosave())
|
||||
self.assertFalse(session.autosave(), "没有新变化就不该重复写库")
|
||||
|
||||
def test_broken_save_degrades_to_a_new_farm(self):
|
||||
path = os.path.join(self.dir, DB_NAME)
|
||||
with open(path, "w", encoding="utf-8") as handle:
|
||||
@@ -247,13 +264,13 @@ class FarmSessionTestCase(unittest.TestCase):
|
||||
|
||||
def test_autosave_skips_when_clean(self):
|
||||
session = FarmSession("alice", self.dir, 2400.0)
|
||||
session.dirty = False
|
||||
session.unsaved = False
|
||||
session.saved_at = 0.0
|
||||
self.assertFalse(session.autosave())
|
||||
|
||||
def test_autosave_writes_when_dirty(self):
|
||||
def test_autosave_writes_when_unsaved(self):
|
||||
session = FarmSession("alice", self.dir, 2400.0)
|
||||
session.dirty = True
|
||||
session.unsaved = True
|
||||
session.saved_at = 0.0
|
||||
self.assertTrue(session.autosave())
|
||||
self.assertTrue(farm_exists(session.db_path, session.farm_id))
|
||||
@@ -377,8 +394,8 @@ class SessionManagerTestCase(unittest.TestCase):
|
||||
manager.get("alice")
|
||||
bob = manager.get("bob")
|
||||
alice = manager.get("alice")
|
||||
alice.dirty = True
|
||||
bob.dirty = False
|
||||
alice.unsaved = True
|
||||
bob.unsaved = False
|
||||
alice.saved_at = bob.saved_at = 0.0
|
||||
self.assertEqual(manager.autosave_all(), 1)
|
||||
|
||||
|
||||
Reference in new issue
Block a user