-
Notifications
You must be signed in to change notification settings - Fork 41
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
feat(env): add environment variables with hot reload for rust code #583
base: feat/env
Are you sure you want to change the base?
Conversation
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.
Left few comments.
If I understand correctly we add the variables to the current process and then we start the server cloning all the variables.
if so I'd suggest to just pass the variables to the server without this back and forth.
Also I noticed that we have a split between system_vars
(I think are the variables set with the tuono
command [do we need to support them?]) and the defined in the .env
files. Do we need such split?
For the record, I'd personally split the env_manager
and watch reload
PRs. Too broad the scopes
Yes that is a better idea.
Yes we should, because these are also other system variables that may be present. They should take priority.
I see how that might be more aligned with atomic PRs, but then we are adding a struct with no usages. The actual bit that handles hot reload is only 10 lines or so, and whilst ordinarily I think they should be split, I think in this case it is better together since the reviewer needs to have the |
My point is that we should prevent the users to start
Good for me keeping everything here. I think this is not the meaning of atomic PR tho. For my experience doing atomic PR means scoping even smaller PR for every change (i.e. create struct, read var, reload var, pass var to process, etc). This because at each review we know exactly what part of the feature you are addressing and it is easier reviewing it and challenging the implementation. 250 new code rows are very though to challenge since there are too moving parts. Knowing the context of a change should come from a meaningful PR description rather than the whole code (we expect that the previous code is correct since already reviewed). No worries here. Let's keep in mind that Atomic PR is meant for better challenging the PRs to deliver higher quality |
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.
Alright. I'd just change the way we pass the data from the CLI to the server process (avoiding having the env cloned on both processes).
I think it is better for a number of reasons, but mostly because it is more readable, and it is not the best using the operating system capabilities for passing the data across the two processes.
Thanks for the feedback, that has made it much clearer. In future I will try to do this.
Ok. Here's my plan:
My concerns with this approach:
I've resolved all of code review, because I'd like to discuss this with you more, so that we can figure out the best implementation together. I'm really open to suggestions or big changes - please let me know :) |
Agree. (Do we need two separate variables for storing system and user defined variables?)
Why you think that? What performance you think we are dropping? The CLI is just a fancy interface to deal with the
|
We would have to load the name and value every variable present on the system, even those completely unrelated to tuono. (Run Maybe this is just not really an issue, but it doesn't feel like the right way to do this. In fact it looks like this is what nodejs does anyway (and I think vite just uses node
Agree. |
Do we have to do this split? What is the benefit of knowing where they came from?
I haven't understood what you are referring to... what should we do? |
The user's OS also has environment variables (eg I was worried because I thought loading all of them was bad, however I think that is just the way they work. So I think it is the right decision to do that (#583 (comment)), since every process should have access to all environment variables. I hope that made a bit more sense (my worries were pretty unfounded I think, so that might be what confused you). I will start implementing this today. |
I think that is not our problem. We should just ignore them.
|
Agree. The only reason we have to interact with them to start with is so that they take precedence over ones from the file. We do still have to collect them because if we do So the plan can stay the same:
Sorry for so much back and forth, but I think it's better to have it here than split through loads of code review sections. Hopefully review can be smoother now :) |
Are you sure about that? I think every process has access to all the system env variables |
Yes you're right, I'm sorry about all that - I was wrong. I read the docs and it looks like Updated plan then (changes are in bold italic):
|
We are on the same page! ⚡ |
I think we should go back to using std::env more. I feel I am reinventing the wheel a bit here, and the code is getting incredibly complex. |
What do you mean?
What are you reinventing? |
The issue is there's not a way to pass in environment variables here: https://github.com/tuono-labs/tuono/blob/19207d7d907fc4598508a5f06f9cfb3f7c29ffb6/crates/tuono/src/watch.rs#L42C1-L62C2. We have to load into OS env at some point - if this is scoped to process, we should move all env code out of the CLI, and into Whilst I appreciate there have been loads of comments, I think EnvManager is still the right way. |
Yeah I think the Consider doing a poc with your proposal! |
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.
Overall the implementation looks very good!
I'd add also an integration test just to be sure that the whole flow is covered.
@@ -16,6 +17,7 @@ mod ssr; | |||
mod vite_reverse_proxy; | |||
mod vite_websocket_proxy; | |||
|
|||
pub use env::EnvVarManager; |
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.
We should not expose the EnvManager
to the userland
pub use env::EnvVarManager; | |
use env::EnvVarManager; |
fn test_system_env_var_precedence() { | ||
let env = MockEnv::new(); | ||
|
||
env::set_var("TEST_KEY", "system_value"); |
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.
In my opinion, we should have a env.add_system_var
that keeps track of the added variables so that the cleanup just removes the added vars (same for the files)
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.
Do you mean some method on the env struct that wraps EnvManager, and same for writing files?
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.
in the MockEnv
struct that keeps track of the set files and system vars. This in order to cleanup just what was declarated
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.
Ok, that sounds like a good idea
@@ -0,0 +1,56 @@ | |||
use std::env; |
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'd remove this file.
Integration tests should test the whole flow (not just a part of it). These tests, as they are right now, have basically the same purpose of the units.
We should just add a route in the mock server that returns in the response the value of an env variable that is sets in an env file (created in the MockTuonoServer
struct).
Let me know if that is clear :)
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.
Ok yeah that makes sense. Should it just be an api route that tries to test all of the rules?
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 api route that covers one single rule. Just to be sure that the whole flow is covered.
Checklist
Related issue
Fixes #586
Overview
Rust EnvManager struct and hot reload for serverside env changes (and tests).
New env files created after server start are not loaded in, however any changes to the env files already loaded are auto-applied. This behavior is consistent with vite.