-
Notifications
You must be signed in to change notification settings - Fork 193
Adds support for handle_continue/2 to gen_stage #264
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
Conversation
The EDIT: Added a compile time conditional that checks the OTP major version, if there's a better way let me know! 😃 |
The failing test seems to be inherently flakey - I can reproduce on master. Not sure what's causing it but running mix test on a loop it occasionally shows up, can investigate separately:
|
* {:continue, _term} instructions can now be returned as one would expect from gen_server. * :hibernate is now supported on init similar to gen_server.
Rebased for #265 |
@josevalim is there something I need to do to move this forward? |
Hi @hazardfn, apparently this fell under the cracks, sorry about that. I will try to save some time to review it this week but it may take a while because there are quite some factors to consider here. In any case, thanks for the PR and the ping! |
Would love this feature. Anything I can do to help test/QA/review? |
when new_state: term, event: term | ||
|
||
@doc """ | ||
Invoked to handle `continue` instructions. |
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.
Invoked to handle `continue` instructions. | |
Invoked to handle `:continue` instructions. |
It is useful for performing work after initialization or for splitting the work | ||
in a callback in multiple steps, updating the process state along the way. |
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 this might be a bit misleading. I think the biggest use of this is being able to emit events and then do something right after, being sure that no messages, calls, or anything else will be "injected" in between. Maybe we can rephrase this?
My suggestion:
It is useful for performing work after initialization or for splitting the work | |
in a callback in multiple steps, updating the process state along the way. | |
This callback can be used to perform work right after emitting events from | |
other callbacks. The "continue mechanism" makes sure that no messages, | |
calls, casts, or anything else will be handled between a callback emitting | |
a `:continue` tuple and the `c:handle_continue/2` callback being invoked. |
Return values are the same as `c:handle_cast/2`. | ||
|
||
This callback is optional. If one is not implemented, the server will fail | ||
if a continue instruction is used. |
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 a continue instruction is used. | |
if a `:continue` instruction is used. |
{:producer, state, {:continue, _term} = continue} -> | ||
init_producer(mod, [], state, continue) | ||
|
||
{:producer, state, :hibernate} -> |
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 would force these return values to be {:producer, state, [], {:continue, term} | :hibernate}
to simplify the API. Thoughts? Same for the cases below with producer_consumer and consumer.
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 agree this incredibly long case statement is less than ideal but if I understand your suggestion correctly wouldn't this result in the GenStage not being initialized (validation/state setup) properly at all in the :hibernate
case and in the {:continue, term}
case initialization of the GenStage state would be forced upon the user...?
EDIT: Actually I think in the continue case it wouldn't work either because if I remember correctly user code only has access to the "inner" user state of the GenStage not the internals...
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 you're OK with keeping the current logic as it is it might be cleaner to pull all this out into a pattern matched group of functions 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.
Right now you have a few extra cases because of the fact that you are allowing the third element of the tuple to be either the options, :hibernate
, or {:continue, term}
. What I am suggesting is that you don't allow it to be the options. The spec of the return would become something like {:producer, state :: term, options :: keyword, :hibernate | {:continue, term}}
.
This way, you shave off a few case clauses by forcing users to use an empty list of options ([]
) if they have no options to pass but still want to use :hibernate
or {:continue, term}
. Does it make more sense?
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.
Right I see, thanks for the clarification! I'll look into these changes tonight 👍
Just checking in to say I won't have as much time as I thought tonight, will post here when I'm able to actually take a bite out of this. |
This would be incredible to have access to. |
Closed in favour of #300. |
Attempts to revive #227