-
-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for callback functions around worker process events #153
Conversation
@elbrujohalcon when improving esl/MongooseIM to use
|
bdd5787
to
083c64c
Compare
Hi @michalwski. I like the concept in principle but I have a few concerns. Crashes / TimeoutsAs it is implemented now, callbacks my crash the process (we're not checking them for errors) and they can also block it (they are run sequentially within the Specs / TypesI would like to be more strict on what a callback function can be, for that I would prefer, if possible, to turn MultiplicityIt seems like you're only allowing one function per callback. In general, it might be nice to allow users to dynamically add/remove various functions to each callback. Existing FunctionalityConsidering these previous items, my mind immediately jumps to Hey! Don't we have a generic way to implement callbacks anywhere? And I think, can't we implement this with |
Thanks for you reply @elbrujohalcon. The I agree with all other points, this PR was just an initial work to show the idea. I'll continue working on it. |
After giving it more thought implementing these callbacks with
What do you think about this @elbrujohalcon? |
Yeah, that's fine. Defining a new behavior |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's good progress in general, but I think it needs some tweaking.
src/wpool_pool.erl
Outdated
-spec add_callback_module(wpool:name(), module()) -> ok | {error, term()}. | ||
add_callback_module(Pool, Module) -> | ||
EventManager = event_manager_name(Pool), | ||
ok = gen_event:call(EventManager, wpool_process_callbacks, {add_callback, Module}). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why instead of having a single event handler and adding callbacks to its list, don't we let gen_event
take care of that and just add a new event handler per module?
This function would use gen_event:add_handler(EventManager, {wpool_process_callbacks, Module}, Module)
and the one below gen_event:delete_handler(EventManager, {wpool_process_callbacks, Module}).
src/wpool_process_callbacks.erl
Outdated
|
||
-spec handle_event({event(), [any()]}, state()) -> {ok, state()}. | ||
handle_event({Event, Args}, Callbacks) -> | ||
[call(Callback, Event, Args) || Callback <- Callbacks], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If instead of managing a list of callbacks here, we let gen_event
take care of that, this module (and in particular this function and the one below) will be simplified.
src/wpool_pool.erl
Outdated
, permanent | ||
, brutal_kill | ||
, worker | ||
, [gen_event] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the right value for this element is dynamic
src/wpool_pool.erl
Outdated
@@ -340,6 +364,8 @@ process_sup_name(Sup) -> | |||
list_to_atom(?MODULE_STRING ++ [$-|atom_to_list(Sup)] ++ "-process-sup"). | |||
queue_manager_name(Sup) -> | |||
list_to_atom(?MODULE_STRING ++ [$-|atom_to_list(Sup)] ++ "-queue-manager"). | |||
event_manager_name(Sup) -> | |||
list_to_atom(?MODULE_STRING ++ [$-|atom_to_list(Sup)] ++ "-event-handler"). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be -event-manager
or -event-dispatcher
, this one is not a handler.
src/wpool_process_callbacks.erl
Outdated
|
||
-spec init([wpool:option()]) -> {ok, state()}. | ||
init(WPoolOpts) -> | ||
{ok, maybe_initial_callbacks(WPoolOpts)}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indentation :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, if instead of managing a list of callbacks here, we let gen_event
take care of that, we won't need to initialize the list of callbacks here. We should do it in wpool_pool:start_link(…)
, probably after initializing the pool itself.
src/wpool_process_callbacks.erl
Outdated
-export([notify/3]). | ||
-type state() :: ordset:ordset(module()). | ||
|
||
-type event() :: on_init_start | on_new_worker | on_worker_dead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This module will define -callbacks
for these 3 event types, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, to preserve the style of other behaviors, I would call them handle_worker_init
, handle_worker_creation
and handle_worker_death
(or similar handle_<something>
names).
@@ -34,6 +34,7 @@ start_link(Parent, Name, Options) -> | |||
init({Name, Options}) -> | |||
Workers = proplists:get_value(workers, Options, 100), | |||
Strategy = proplists:get_value(strategy, Options, {one_for_one, 5, 60}), | |||
maybe_add_event_handler(Options), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If instead of managing a list of callbacks ourselves, we let gen_event
take care of that, this won't be needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still needed in order to add the initial callbacks passed in opts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still needed in order to add the initial callbacks passed in opts.
Thanks for all the comments @elbrujohalcon. This PR was not ready yet but it's good to have a feedback as early as possible! I'll apply changes based on your review and let you know when I consider the work finished. |
bf7562f
to
37c7c38
Compare
Triggering travis. |
0e4b456
to
dafe599
Compare
@elbrujohalcon I consider this PR finished. Do you have any other comments? |
Codecov Report
@@ Coverage Diff @@
## rel-3.1 #153 +/- ##
===========================================
- Coverage 95.73% 95.06% -0.68%
===========================================
Files 9 10 +1
Lines 399 446 +47
===========================================
+ Hits 382 424 +42
- Misses 17 22 +5
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really really good. Awesome job, @michalwski !! 💯
Just a few minor tweaks and we're done!
src/wpool_process_callbacks.erl
Outdated
, handle_call/2 | ||
, handle_info/2 | ||
, code_change/3 | ||
, terminate/2]). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
, terminate/2]). | |
, terminate/2 | |
]). |
src/wpool_process_sup.erl
Outdated
undefined -> | ||
ok; | ||
EventMgr -> | ||
[gen_event:add_handler(EventMgr, {wpool_process_callbacks, Module}, Module) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we don't care about the result of this list comprehension, why not using lists:foreach
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List comprehension feels more natural for me, that's why I used it here. There is no need to create a fun fro that, we can use the gen_event:add_handler
directly here.
To optimize the code a bit I can return ok
just after the list comprehension so the result will go to garbage sooner.
If you insist I can change to lists:foreach
.
@elbrujohalcon I think all the comments/suggestions were addressed in the latest commit. |
30b1246
to
1451eea
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one final change, now that we moved to lists:foreach/2
(thanks for that, BTW)
Note to self:
|
@michalwski you might want to consider adding something like worker_pool/test/wpool_worker_SUITE.erl Line 76 in 05a2411
|
Co-Authored-By: michalwski <[email protected]>
@michalwski it's approved. GREAT WORK! Merge it when you feel like it and I'll take care of propagating this changes to |
I'm not sure about it. I'm fine with these 3 lines not covered. I can add it if you insist, though. |
I don't insist, we have #98 and most of them will go away with the usage of optional callbacks when migrating to |
I'll merge it later today. |
@elbrujohalcon thanks for all your reviews and good suggestions! |
This PR allows to set callback funs for following events in worker process:
on_init_started
- initialization started (before module's init function is calledon_new_worker
- when the module's init function returns with result{ok, State}
or{ok, State, Timeout}
on_worker_dead
- when worker process terminatesThese callbacks can be used by
worker_pool
users in order to increase relevant metrics or add logging when needed.