typestate.gleam
1 //// Typestate lifecycle for Lightspeed session agents. 2 3 /// Marker type for a disconnected agent. 4 pub type Disconnected { 5 Disconnected 6 } 7 8 /// Marker type for an agent performing protocol handshake. 9 pub type Handshaking { 10 Handshaking 11 } 12 13 /// Marker type for an agent whose component has mounted. 14 pub type Mounted { 15 Mounted 16 } 17 18 /// Marker type for an active live agent. 19 pub type Live { 20 Live 21 } 22 23 /// Marker type for an agent draining before shutdown. 24 pub type Draining { 25 Draining 26 } 27 28 /// Marker type for a terminated agent. 29 pub type Terminated { 30 Terminated 31 } 32 33 /// Lifecycle labels useful for logs and protocol diagnostics. 34 pub type Lifecycle { 35 DisconnectedLabel 36 HandshakingLabel 37 MountedLabel 38 LiveLabel 39 DrainingLabel 40 TerminatedLabel 41 } 42 43 /// A session agent parameterized by lifecycle state. 44 pub opaque type Agent(state) { 45 Agent(id: String, label: Lifecycle) 46 } 47 48 /// Create a disconnected agent. 49 pub fn new(id: String) -> Agent(Disconnected) { 50 Agent(id: id, label: DisconnectedLabel) 51 } 52 53 /// Transition from disconnected to handshaking. 54 pub fn handshake(agent: Agent(Disconnected)) -> Agent(Handshaking) { 55 Agent(id: agent.id, label: HandshakingLabel) 56 } 57 58 /// Transition from handshaking to mounted. 59 pub fn mount(agent: Agent(Handshaking)) -> Agent(Mounted) { 60 Agent(id: agent.id, label: MountedLabel) 61 } 62 63 /// Transition from mounted to live. 64 pub fn go_live(agent: Agent(Mounted)) -> Agent(Live) { 65 Agent(id: agent.id, label: LiveLabel) 66 } 67 68 /// Transition from live to draining. 69 pub fn drain(agent: Agent(Live)) -> Agent(Draining) { 70 Agent(id: agent.id, label: DrainingLabel) 71 } 72 73 /// Transition from draining to terminated. 74 pub fn terminate(agent: Agent(Draining)) -> Agent(Terminated) { 75 Agent(id: agent.id, label: TerminatedLabel) 76 } 77 78 /// Return the agent id. 79 pub fn id(agent: Agent(state)) -> String { 80 agent.id 81 } 82 83 /// Return the lifecycle label. 84 pub fn lifecycle(agent: Agent(state)) -> Lifecycle { 85 agent.label 86 } 87 88 /// Convert a lifecycle label to a stable string. 89 pub fn lifecycle_to_string(lifecycle: Lifecycle) -> String { 90 case lifecycle { 91 DisconnectedLabel -> "disconnected" 92 HandshakingLabel -> "handshaking" 93 MountedLabel -> "mounted" 94 LiveLabel -> "live" 95 DrainingLabel -> "draining" 96 TerminatedLabel -> "terminated" 97 } 98 }