Skip to content
Browse files

Add typespecs and test Kevin Smith's worker init/stop functionality

  • Loading branch information...
1 parent 2b37986 commit e6aeeff113e097be7ab183f9ce1cd31dd1a61425 Devin Torres committed
Showing with 76 additions and 20 deletions.
  1. 0 .dialyzer-ignore-warnings
  2. +2 −1 Makefile
  3. BIN rebar
  4. +1 −1 src/poolboy.app.src
  5. +31 −18 src/poolboy.erl
  6. +42 −0 test/poolboy_tests.erl
View
0 .dialyzer-ignore-warnings
No changes.
View
3 Makefile
@@ -22,4 +22,5 @@ build-plt:
--apps kernel stdlib
dialyze: compile
- @$(DIALYZER) --src src --plt .dialyzer_plt $(DIALYZER_WARNINGS)
+ @$(DIALYZER) --src src --plt .dialyzer_plt $(DIALYZER_WARNINGS) | \
+ fgrep -vf .dialyzer-ignore-warnings
View
BIN rebar
Binary file not shown.
View
2 src/poolboy.app.src
@@ -1,6 +1,6 @@
{application, poolboy, [
{description, "A hunky Erlang worker pool factory"},
- {vsn, "0.4"},
+ {vsn, "0.5"},
{applications, [kernel, stdlib]},
{registered, []}
]}.
View
49 src/poolboy.erl
@@ -12,19 +12,32 @@
-define(DEFAULT_INIT_FUN, fun(Worker) -> {ok, Worker} end).
-define(DEFAULT_STOP_FUN, fun(Worker) -> Worker ! stop end).
--record(state, {workers, worker_sup, waiting=queue:new(), monitors=[],
- size=5, overflow=0, max_overflow=10, worker_init=?DEFAULT_INIT_FUN,
- worker_stop=?DEFAULT_STOP_FUN}).
+-record(state, {
+ workers :: queue(),
+ worker_sup :: pid(),
+ waiting = queue:new() :: queue(),
+ monitors = [] :: list(),
+ size = 5 :: non_neg_integer(),
+ overflow = 0 :: non_neg_integer(),
+ max_overflow = 10 :: non_neg_integer(),
+ worker_init = ?DEFAULT_INIT_FUN :: fun(),
+ worker_stop = ?DEFAULT_STOP_FUN :: fun()
+}).
+-spec checkout(Pool :: node()) -> pid().
checkout(Pool) ->
- checkout(Pool, true, ?TIMEOUT).
+ checkout(Pool, true).
+-spec checkout(Pool :: node(), true) -> pid() | full.
checkout(Pool, Block) ->
checkout(Pool, Block, ?TIMEOUT).
+-spec checkout(Pool :: node(), Block :: boolean(), Timeout :: timeout())
+ -> pid() | full.
checkout(Pool, Block, Timeout) ->
gen_fsm:sync_send_event(Pool, {checkout, Block}, Timeout).
+-spec checkin(Pool :: node(), Worker :: pid()) -> 'ok'.
checkin(Pool, Worker) ->
gen_fsm:send_event(Pool, {checkin, Worker}).
@@ -38,22 +51,22 @@ start_link(Args) ->
init(Args) ->
process_flag(trap_exit, true),
- init(Args, Args, #state{}).
+ init(Args, #state{}).
-init([{worker_module, Mod} | Rest], AllArgs, State) ->
+init([{worker_module, Mod} | Rest], State) ->
{ok, Sup} = poolboy_sup:start_link(Mod, Rest),
- init(Rest, AllArgs, State#state{worker_sup=Sup});
-init([{size, PoolSize} | Rest], AllArgs, State) ->
- init(Rest, AllArgs, State#state{size=PoolSize});
-init([{max_overflow, MaxOverflow} | Rest], AllArgs, State) ->
- init(Rest, AllArgs, State#state{max_overflow=MaxOverflow});
-init([{init_fun, InitFun} | Rest], AllArgs, State) when is_function(InitFun) ->
- init(Rest, AllArgs, State#state{worker_init=InitFun});
-init([{stop_fun, StopFun} | Rest], AllArgs, State) when is_function(StopFun) ->
- init(Rest, AllArgs, State#state{worker_stop=StopFun});
-init([_ | Rest], AllArgs, State) ->
- init(Rest, AllArgs, State);
-init([], _AllArgs, #state{size=Size, worker_sup=Sup, worker_init=InitFun}=State) ->
+ init(Rest, State#state{worker_sup=Sup});
+init([{size, Size} | Rest], State) ->
+ init(Rest, State#state{size=Size});
+init([{max_overflow, MaxOverflow} | Rest], State) ->
+ init(Rest, State#state{max_overflow=MaxOverflow});
+init([{init_fun, InitFun} | Rest], State) when is_function(InitFun) ->
+ init(Rest, State#state{worker_init=InitFun});
+init([{stop_fun, StopFun} | Rest], State) when is_function(StopFun) ->
+ init(Rest, State#state{worker_stop=StopFun});
+init([_ | Rest], State) ->
+ init(Rest, State);
+init([], #state{size=Size, worker_sup=Sup, worker_init=InitFun}=State) ->
Workers = prepopulate(Size, Sup, InitFun),
{ok, ready, State#state{workers=Workers}}.
View
42 test/poolboy_tests.erl
@@ -47,6 +47,12 @@ pool_test_() ->
},
{<<"Pool behaves on owner death">>,
fun owner_death/0
+ },
+ {<<"Pool worker init function called when workers when created">>,
+ fun worker_init_fun/0
+ },
+ {<<"Pool worker stop function called on workers when destroyed">>,
+ fun worker_stop_fun/0
}
]
}.
@@ -360,3 +366,39 @@ owner_death() ->
?assertEqual(5, length(?sync(Pid, get_all_workers))),
?assertEqual(0, length(?sync(Pid, get_all_monitors))),
ok = ?sync(Pid, stop).
+
+worker_init_fun() ->
+ Self = self(),
+ InitFun = fun(Worker) ->
+ Self ! worked,
+ {ok, Worker}
+ end,
+ {ok, Pid} = poolboy:start_link([{name, {local, poolboy_test}},
+ {worker_module, poolboy_test_worker},
+ {init_fun, InitFun}]),
+ poolboy:checkout(Pid),
+ receive
+ worked -> ?assert(true)
+ after
+ 1000 -> ?assert(false)
+ end,
+ ok = ?sync(Pid, stop).
+
+worker_stop_fun() ->
+ Self = self(),
+ StopFun = fun(Worker) ->
+ Self ! worked,
+ Worker ! stop
+ end,
+ {ok, Pid} = poolboy:start_link([{name, {local, poolboy_test}},
+ {worker_module, poolboy_test_worker},
+ {stop_fun, StopFun},
+ {size, 0}, {max_overflow, 1}]),
+ Worker = poolboy:checkout(Pid),
+ checkin_worker(Pid, Worker),
+ receive
+ worked -> ?assert(true)
+ after
+ 1000 -> ?assert(false)
+ end,
+ ok = ?sync(Pid, stop).

0 comments on commit e6aeeff

Please sign in to comment.
Something went wrong with that request. Please try again.