@@ -160,4 +160,86 @@ defmodule GenServers do
160
160
161
161
:ok = Laptop . stop ( )
162
162
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
163
245
end
0 commit comments