Skip to content
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

Implement handle_cast and handle_continue #88

Merged
merged 2 commits into from
Jul 3, 2024

Conversation

pjlast
Copy link
Contributor

@pjlast pjlast commented Jul 2, 2024

Closes #4

This PR implements the handle_cast and handle_continue Gen_server methods from Erlang. It also reworks the responses for the handle_* methods a bit so that handle_continue can be called.

Request types

You'll see there are two new request types: cast_req and cont_req. These are separate from the current req type used in handle_call (which should maybe be renamed to call_req. The reason I added these is because handle_call, handle_cast and handle_continue will have different requests that can be sent to them. It doesn't make sense to be able to send a call request to handle_cast and then having to deal with a potential error/exception if we can prevent it from being valid at all. handle_cast and handle_continue also don't respond to the client, so they also don't need a 'res type.

Result types

I also changed handle_call to return a new call_result type instead to accommodate for the different ways a Gen_server can respond in Elixir. Reply ('res * 'state) is the regular reply it's been using thus far. But to accommodate handle_continue, handle_call needs to be able to respond with a {:continue, args} as well like you can do in Elixir. For this I added a Reply_continue as well, which takes the form ('res * 'state * cont_req), where cont_req will be handled by handle_continue after the 'res has been sent to the client.

Similarly, cast_result has a No_reply, which is equivalent to the Elixir {:noreply, state} response. This can be extended for a No_reply_continue option as well, or whatever else GenServers in Elixir allows.

In Elixir (or Erlang I guess), handle_call can respond with a {:noreply, ...} as well, which assumes that the user manually responded with a reply(pid, res) somewhere in the handler. This is useful for when the reply is known already, but additional work needs to be done by the server. I opted not to implement this, as it leads to potential error states where the user perhaps doesn't do a reply in the handler, or perhaps does two replys. I also think most behaviours requiring this can be implemented with handle_continue, which leaves less room for error.

@pjlast
Copy link
Contributor Author

pjlast commented Jul 2, 2024

@leostera this changes the interface of how you implement Gen_servers a bit, but I think it's the easiest way to get closer to parity with the Elixir GenServers (which fake the Algebraic Data Types with the {:reply, ...}, '{:noreply, ...}` etc. tuples anyways)

@leostera
Copy link
Collaborator

leostera commented Jul 3, 2024

Excellent! 👏🏼 Thanks @pjlast! Let's merge and we can improve / change over time.

@leostera leostera merged commit ac9e22f into riot-ml:main Jul 3, 2024
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add missing GenServer callbacks
2 participants