Files

83 lines
3.2 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Foundation
/// LaunchAgent 注册态(GUI 视角):SMAppService.Status 的纯域
/// 映射。SMAppService 不暴露运行中 agent 的 pid,wrapper 活性另由
/// `WrapperProcessState` 表达。
enum LaunchAgentStatus: Equatable, Sendable {
case notRegistered
/// 已注册(无论 wrapper 进程当前是否在运行)。
case registered
/// 需要用户在系统设置的登录项中批准。
case requiresApproval
/// 注册清单缺失(bundle 内 plist 不在)。
case notFound
}
/// wrapper 进程活性:GUI 读 `agent.pid` 并以 `kill(pid, 0)` 判定。
enum WrapperProcessState: Equatable, Sendable {
case notRunning
case running(pid: Int32)
}
/// GUI 对代理运行时的意图:运行给定义档,或停止并清理。
enum RuntimeIntent: Equatable {
case run(SslocalRuntimeDocument)
case stop
}
/// 控制器按序执行的动作。
enum RuntimeAction: Equatable, Sendable {
/// 原子写契约文件(权限与替换基线由 RuntimeFileStore 保证)。
case writeContract
/// 注册 LaunchAgent;launchd 随即拉起 wrapper,wrapper 启动时读契约。
case registerAgent
/// 注销 LaunchAgent:launchd 以 SIGTERM 结束 wrapper,触发显式停止协议
/// (wrapper 停 sslocal 并等待退出)。
case unregisterAgent
/// 通知运行中的 wrapper 重读契约;热重载或优雅重启由 wrapper 按监听
/// 指纹判定遵循变更协议。
case signalReload(pid: Int32)
/// 删除运行时文件(契约、pid 文件与残留临时文件)。
case deleteRuntimeFiles
}
/// 纯决策层:把「代理意图 + launchd 注册态 + wrapper 活性
/// + 磁盘契约」推到有序动作序列。GUI 启动重同步、目录提交重展开与代理开关
/// 共用同一决策;相同契约内容跳过写入,兑现激活状态机的幂等注记。
enum ProxyRuntimePlan {
static func actions(
intent: RuntimeIntent,
agentStatus: LaunchAgentStatus,
wrapper: WrapperProcessState,
configurationIsCurrent: Bool
) -> [RuntimeAction] {
switch intent {
case .run:
switch agentStatus {
case .notRegistered, .notFound, .requiresApproval:
// 首次启用或从未注册:写盘后注册,launchd 拉起的 wrapper 直接读新档。
return [.writeContract, .registerAgent]
case .registered:
switch wrapper {
case .running(let pid):
if configurationIsCurrent { return [] }
return [.writeContract, .signalReload(pid: pid)]
case .notRunning:
// 已注册但 wrapper 已干净退出(如契约曾被清理):强制重新拉起。
// SMAppService 对已注册服务重复 register 不保证重跑,先注销再注册。
return [.writeContract, .unregisterAgent, .registerAgent]
}
}
case .stop:
switch agentStatus {
case .registered:
// 显式停止协议次序:注销即 SIGTERM wrapper → wrapper 停 sslocal
// 并等待 → 控制器确认 wrapper 退出后才删文件(执行侧保证次序)。
return [.unregisterAgent, .deleteRuntimeFiles]
case .notRegistered, .requiresApproval, .notFound:
return [.deleteRuntimeFiles]
}
}
}
}