Coverage for src\genesis\state_machine.py: 100%

40 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-26 14:20 +0800

1from __future__ import annotations 

2 

3from typing import Literal 

4 

5# 会话级状态集(9 个):8 个设计态 + cancelled(T3 架构审查整改) 

6SessionState = Literal[ 

7 "uploading", 

8 "parsing", 

9 "awaiting_parse_confirm", 

10 "impact_running", 

11 "awaiting_impact_confirm", 

12 "writing", 

13 "qa", 

14 "done", 

15 "cancelled", 

16] 

17 

18STATES: frozenset[str] = frozenset({ 

19 "uploading", 

20 "parsing", 

21 "awaiting_parse_confirm", 

22 "impact_running", 

23 "awaiting_impact_confirm", 

24 "writing", 

25 "qa", 

26 "done", 

27 "cancelled", 

28}) 

29 

30# 合法转移白名单(不含 cancelled 的动态 resume 转移,见 SessionStateMachine.resume) 

31_TRANSITIONS: dict[str, frozenset[str]] = { 

32 "uploading": frozenset({"parsing"}), 

33 "parsing": frozenset({"awaiting_parse_confirm", "cancelled"}), 

34 "awaiting_parse_confirm": frozenset({"impact_running", "parsing", "cancelled"}), 

35 "impact_running": frozenset({"awaiting_impact_confirm", "cancelled"}), 

36 "awaiting_impact_confirm": frozenset({"writing", "impact_running", "awaiting_parse_confirm", "cancelled"}), 

37 "writing": frozenset({"qa", "awaiting_impact_confirm", "cancelled"}), 

38 "qa": frozenset({"done", "writing", "cancelled"}), 

39 "done": frozenset(), 

40 "cancelled": frozenset(), 

41} 

42 

43# 可被取消的(非终态、非人工等待确认态之外全部执行中;done 不可取消) 

44_CANCELLABLE: frozenset[str] = frozenset({ 

45 "parsing", 

46 "impact_running", 

47 "writing", 

48 "qa", 

49}) 

50 

51 

52class StateTransitionError(Exception): 

53 """非法状态转移(对应 api-design §7 STATE_TRANSITION_INVALID 409)。""" 

54 

55 

56class SessionStateMachine: 

57 """会话级流程状态机:白名单转移 + cancelled/resume(T3)。 

58 

59 取消(cancel)从任意执行中状态进入 cancelled 终态,并记录中断前状态 

60 (cancelled_from);resume 从 cancelled 回到中断前状态,恢复后继续 

61 正常白名单流转。人工等待确认态(awaiting_*)与 done 不可取消。 

62 """ 

63 

64 def __init__(self, initial: str = "uploading") -> None: 

65 if initial not in STATES: 

66 raise StateTransitionError(f"未知初始状态: {initial}") 

67 self._state: str = initial 

68 self._cancelled_from: str | None = None 

69 

70 @property 

71 def state(self) -> str: 

72 return self._state 

73 

74 @property 

75 def cancelled_from(self) -> str | None: 

76 """取消前的中断状态(resume 目标);仅 cancelled 态非 None。""" 

77 return self._cancelled_from 

78 

79 def transition(self, target: str) -> str: 

80 """按白名单推进状态机;非法转移抛 StateTransitionError。""" 

81 if target not in STATES: 

82 raise StateTransitionError(f"未知目标状态: {target}") 

83 allowed = _TRANSITIONS[self._state] 

84 if target not in allowed: 

85 raise StateTransitionError( 

86 f"非法状态转移: {self._state}{target}(白名单外)" 

87 ) 

88 self._state = target 

89 return self._state 

90 

91 def cancel(self) -> str: 

92 """取消当前执行:进入 cancelled 终态,记录中断前状态。""" 

93 if self._state not in _CANCELLABLE: 

94 raise StateTransitionError( 

95 f"当前状态不可取消: {self._state}(仅执行中状态可取消)" 

96 ) 

97 self._cancelled_from = self._state 

98 self._state = "cancelled" 

99 return self._state 

100 

101 def resume(self) -> str: 

102 """从 cancelled 恢复:回到中断前状态(cancelled_from)。""" 

103 if self._state != "cancelled": 

104 raise StateTransitionError( 

105 f"仅 cancelled 状态可 resume(当前: {self._state}" 

106 ) 

107 assert self._cancelled_from is not None # cancelled 态必有记录 

108 self._state = self._cancelled_from 

109 self._cancelled_from = None 

110 return self._state