|
23 | 23 | add_worker_to_cleaner/2
|
24 | 24 | ]).
|
25 | 25 |
|
26 |
| --include_lib("fabric/include/fabric.hrl"). |
27 | 26 | -include_lib("mem3/include/mem3.hrl").
|
28 | 27 |
|
| 28 | +-record(stream_acc, { |
| 29 | + workers, |
| 30 | + ready, |
| 31 | + start_fun, |
| 32 | + replacements, |
| 33 | + ring_opts |
| 34 | +}). |
| 35 | + |
29 | 36 | -define(WORKER_CLEANER, fabric_worker_cleaner).
|
30 | 37 |
|
31 | 38 | % This is the streams equivalent of fabric_util:submit_jobs/4. Besides
|
@@ -77,7 +84,12 @@ start(Workers0, Keypos, StartFun, Replacements, RingOpts) ->
|
77 | 84 | Workers
|
78 | 85 | ),
|
79 | 86 | {ok, AckedWorkers};
|
| 87 | + {timeout, #stream_acc{workers = Defunct}} -> |
| 88 | + cleanup(Workers0), |
| 89 | + DefunctWorkers = fabric_util:remove_done_workers(Defunct, waiting), |
| 90 | + {timeout, DefunctWorkers}; |
80 | 91 | Else ->
|
| 92 | + cleanup(Workers0), |
81 | 93 | Else
|
82 | 94 | end.
|
83 | 95 |
|
@@ -165,10 +177,7 @@ handle_stream_start(rexi_STREAM_INIT, {Worker, From}, St) ->
|
165 | 177 | {stop, St#stream_acc{workers = [], ready = Ready1}}
|
166 | 178 | end
|
167 | 179 | end;
|
168 |
| -handle_stream_start({ok, Error}, _, St) when Error == ddoc_updated; Error == insufficient_storage -> |
169 |
| - WaitingWorkers = [W || {W, _} <- St#stream_acc.workers], |
170 |
| - ReadyWorkers = [W || {W, _} <- St#stream_acc.ready], |
171 |
| - cleanup(WaitingWorkers ++ ReadyWorkers), |
| 180 | +handle_stream_start({ok, Error}, _, _) when Error == ddoc_updated; Error == insufficient_storage -> |
172 | 181 | {stop, Error};
|
173 | 182 | handle_stream_start(Else, _, _) ->
|
174 | 183 | exit({invalid_stream_start, Else}).
|
@@ -236,7 +245,9 @@ worker_cleaner_test_() ->
|
236 | 245 | ?TDEF_FE(should_clean_additional_worker_too),
|
237 | 246 | ?TDEF_FE(coordinator_is_killed_if_client_disconnects),
|
238 | 247 | ?TDEF_FE(coordinator_is_not_killed_if_client_is_connected),
|
239 |
| - ?TDEF_FE(submit_jobs_sets_up_cleaner) |
| 248 | + ?TDEF_FE(submit_jobs_sets_up_cleaner), |
| 249 | + ?TDEF_FE(cleanup_called_on_timeout), |
| 250 | + ?TDEF_FE(cleanup_called_on_error) |
240 | 251 | ]
|
241 | 252 | }
|
242 | 253 | }.
|
@@ -442,7 +453,39 @@ submit_jobs_sets_up_cleaner(_) ->
|
442 | 453 | ?assert(is_process_alive(Cleaner))
|
443 | 454 | end.
|
444 | 455 |
|
| 456 | +cleanup_called_on_timeout(_) -> |
| 457 | + Ref1 = make_ref(), |
| 458 | + Ref2 = make_ref(), |
| 459 | + W1 = #shard{node = 'n1', ref = Ref1}, |
| 460 | + W2 = #shard{node = 'n2', ref = Ref2}, |
| 461 | + Workers = [W1, W2], |
| 462 | + meck:expect(rexi_utils, recv, fun(_, _, _, Acc, _, _) -> |
| 463 | + {timeout, Acc#stream_acc{workers = [{W2, waiting}]}} |
| 464 | + end), |
| 465 | + meck:reset(fabric_util), |
| 466 | + Res = start(Workers, #shard.ref, undefined, undefined, []), |
| 467 | + ?assertEqual({timeout, [W2]}, Res), |
| 468 | + ?assert(meck:called(fabric_util, cleanup, 1)). |
| 469 | + |
| 470 | +cleanup_called_on_error(_) -> |
| 471 | + Ref1 = make_ref(), |
| 472 | + Ref2 = make_ref(), |
| 473 | + W1 = #shard{node = 'n1', ref = Ref1}, |
| 474 | + W2 = #shard{node = 'n2', ref = Ref2}, |
| 475 | + Workers = [W1, W2], |
| 476 | + meck:expect(rexi_utils, recv, fun(_, _, _, _, _, _) -> |
| 477 | + {error, foo} |
| 478 | + end), |
| 479 | + meck:reset(fabric_util), |
| 480 | + Res = start(Workers, #shard.ref, undefined, undefined, []), |
| 481 | + ?assertEqual({error, foo}, Res), |
| 482 | + ?assert(meck:called(fabric_util, cleanup, 1)). |
| 483 | + |
445 | 484 | setup() ->
|
| 485 | + ok = meck:new(rexi_utils, [passthrough]), |
| 486 | + ok = meck:new(config, [passthrough]), |
| 487 | + ok = meck:new(fabric_util, [passthrough]), |
| 488 | + meck:expect(config, get, fun(_, _, Default) -> Default end), |
446 | 489 | ok = meck:expect(rexi, kill_all, fun(_) -> ok end),
|
447 | 490 | % Speed up disconnect socket timeout for the test to 200 msec
|
448 | 491 | ok = meck:expect(chttpd_util, mochiweb_client_req_check_msec, 0, 200).
|
|
0 commit comments