@@ -160,4 +160,86 @@ defmodule GenServers do
160160
161161 :ok = Laptop . stop ( )
162162 end
163+
164+ defmodule TimeoutServer do
165+ use GenServer
166+
167+ def start_link ( timeout ) do
168+ GenServer . start_link ( __MODULE__ , timeout , name: __MODULE__ )
169+ end
170+
171+ def init ( timeout ) do
172+ { :ok , % { count: 0 } , timeout }
173+ end
174+
175+ def get_count do
176+ GenServer . call ( __MODULE__ , :get_count )
177+ end
178+
179+ def handle_call ( :get_count , _from , state ) do
180+ { :reply , state . count , state }
181+ end
182+
183+ def handle_info ( :timeout , state ) do
184+ new_state = % { state | count: state . count + 1 }
185+ { :noreply , new_state }
186+ end
187+ end
188+
189+ koan "GenServers can handle info messages and timeouts" do
190+ { :ok , _pid } = TimeoutServer . start_link ( 100 )
191+ # Wait for timeout to occur
192+ :timer . sleep ( 101 )
193+ count = TimeoutServer . get_count ( )
194+ assert count == ___
195+
196+ GenServer . stop ( TimeoutServer )
197+ end
198+
199+ defmodule CrashableServer do
200+ use GenServer
201+
202+ def start_link ( initial ) do
203+ GenServer . start_link ( __MODULE__ , initial , name: __MODULE__ )
204+ end
205+
206+ def init ( initial ) do
207+ { :ok , initial }
208+ end
209+
210+ def crash do
211+ GenServer . cast ( __MODULE__ , :crash )
212+ end
213+
214+ def get_state do
215+ GenServer . call ( __MODULE__ , :get_state )
216+ end
217+
218+ def handle_call ( :get_state , _from , state ) do
219+ { :reply , state , state }
220+ end
221+
222+ def handle_cast ( :crash , _state ) do
223+ raise "Intentional crash for testing"
224+ end
225+ end
226+
227+ koan "GenServers can be supervised and restarted" do
228+ # Start under a supervisor
229+ children = [ { CrashableServer , "the state" } ]
230+ { :ok , supervisor } = Supervisor . start_link ( children , strategy: :one_for_one )
231+
232+ # Server should be running
233+ initial_state = CrashableServer . get_state ( )
234+ assert initial_state == ___
235+
236+ :ok = CrashableServer . crash ( )
237+ # Wait for recovery
238+ :timer . sleep ( 100 )
239+
240+ state_after_crash_recovery = CrashableServer . get_state ( )
241+ assert state_after_crash_recovery == ___
242+
243+ Supervisor . stop ( supervisor )
244+ end
163245end
0 commit comments