agentmux_srv\reducer/
lifecycle.rs1use agentmux_common::ipc::{ErrorCode, Event};
5
6use crate::state::State;
7
8use super::Ctx;
9
10use agentmux_common::ipc::{ClientKind, LifecyclePhase};
11use crate::state::{ProcessRecord, ProcessState};
12
13pub(super) fn handle_register(
14 state: &mut State,
15 ctx: &Ctx,
16 kind: ClientKind,
17 pid: u32,
18 version: String,
19) -> Vec<Event> {
20 let prior_state = state.processes.get(&pid).map(|r| r.state);
25 let allow_register = match prior_state {
26 None => true,
27 Some(ProcessState::Exited { .. }) => true,
28 _ => false,
29 };
30 if !allow_register {
31 let v = state.bump_version();
32 return vec![Event::Error {
33 code: ErrorCode::AlreadyRegistered,
34 message: format!("pid {} is already registered with srv", pid),
35 fatal: false,
36 version: v,
37 }];
38 }
39
40 let mut out = Vec::with_capacity(3);
41
42 state.processes.insert(
44 pid,
45 ProcessRecord {
46 pid,
47 kind,
48 state: ProcessState::Running,
49 spawned_at: ctx.now_rfc3339.clone(),
50 version: version.clone(),
51 },
52 );
53 let v = state.bump_version();
54 out.push(Event::ProcessSpawned {
55 pid,
56 kind,
57 client_version: version,
58 version: v,
59 });
60
61 if state.lifecycle == LifecyclePhase::Starting {
64 state.lifecycle = LifecyclePhase::Running;
65 let v = state.bump_version();
66 out.push(Event::LifecyclePhaseChanged {
67 from: LifecyclePhase::Starting,
68 to: LifecyclePhase::Running,
69 version: v,
70 });
71 }
72
73 let client_id = state.alloc_client_id();
74 let v = state.bump_version();
75 out.push(Event::Registered {
78 client_id,
79 launcher_pid: 0,
80 launcher_version: String::new(),
81 version: v,
82 });
83 out
84}
85
86pub(super) fn handle_goodbye(state: &mut State, ctx: &Ctx) -> Vec<Event> {
87 let Some(pid) = ctx.registered_pid else {
88 return Vec::new();
89 };
90 let Some(record) = state.processes.get_mut(&pid) else {
91 return Vec::new();
92 };
93 if matches!(record.state, ProcessState::Exited { .. }) {
94 return Vec::new();
95 }
96 record.state = ProcessState::Exited { code: 0 };
97 let v = state.bump_version();
98 vec![Event::ProcessExited {
99 pid,
100 code: 0,
101 version: v,
102 }]
103}