@@ -7,7 +7,8 @@ suite_test_() ->
77 [
88 {" aggregate_behaviour" , fun aggregate_behaviour /0 },
99 {" aggregate_passivation" , fun aggregate_passivation /0 },
10- {" aggregate_invalid_command" , fun aggregate_invalid_command /0 }
10+ {" aggregate_invalid_command" , fun aggregate_invalid_command /0 },
11+ {" aggregate_survives_dead_worker" , fun aggregate_survives_dead_worker /0 }
1112 ],
1213 {foreach , fun setup /0 , fun teardown /1 , TestCases }.
1314
@@ -173,6 +174,32 @@ aggregate_invalid_command() ->
173174
174175 ? assertEqual (ok , es_kernel_mgr_aggregate :stop (Pid )).
175176
177+ aggregate_survives_dead_worker () ->
178+ Pid = start_mgr (5000 ),
179+ Id = <<" 123" >>,
180+
181+ ? assertEqual (
182+ ok ,
183+ es_kernel_mgr_aggregate :dispatch (Pid , cmd (deposit , Id , #{amount => 100 }))
184+ ),
185+ AggPid = agg_id (Pid , bank_account , Id ),
186+ exit (AggPid , kill ),
187+
188+ % % Dispatch while the cached pid is dead: should not crash manager and should return an error
189+ ? assertMatch (
190+ {error , {aggregate_down , _ }},
191+ es_kernel_mgr_aggregate :dispatch (Pid , cmd (deposit , Id , #{amount => 10 }))
192+ ),
193+
194+ % % Next dispatch should start a fresh aggregate and succeed (rehydrated to previous balance)
195+ ? assertEqual (
196+ ok ,
197+ es_kernel_mgr_aggregate :dispatch (Pid , cmd (deposit , Id , #{amount => 20 }))
198+ ),
199+ ? assertState (agg_id (Pid , bank_account , Id ), Id , #{balance := 120 }, 2 ),
200+
201+ ? assertEqual (ok , es_kernel_mgr_aggregate :stop (Pid )).
202+
176203start_mgr (Timeout ) ->
177204 StoreContext = es_kernel_app :get_store_context (),
178205 {ok , Pid } =
0 commit comments