Last week, I was able to achieve my main goal, my stretch goal, and a couple of other goals. I learned a lot in the process and stayed within a reasonable amount of time, although I think I still could have been more efficient.
My main goal of getting simple forwarding working was relatively straightforward. I have a server that runs on one port, accepts client connections, and forwards them to a different server running on a different port.
My stretch goal of setting up logging was quick due to similarity with previous projects. Right now, I’m pretty much just using it as pretty printing with slightly more information, but doing it this way early means it would be much easier to start using more advanced logging features later.
I had initially planned on multiple concurrent client connections being a distinct goal, but it ended up making more sense to just do it that way from the beginning. Using the common pattern of listening for connections in a loop and spawning a task per client felt more natural than trying to implement it sequentially first.
I also added in the additional goal of header manipulation and learned a bit about this topic. Basically, there are various hop-by-hop HTTP headers that a reverse proxy like this needs to remove/modify, X-Forwarded-For for the client IP (appending if it already exists), and Host for the backend being forwarded to. Of course, there are many others, but I started with these basics and got some tests passing.
My primary goal for this week will be externalizing config in a TOML file. Hardcoded constants are working fine now, but similar to logging, I know I’ll need to do this eventually, so I might as well set it up before it becomes a problem instead of continuing to create code I know I’ll need to refactor. I’m not as familiar with this kind of thing as I am with logging, so I expect it to take slightly more time, but still be quite manageable.
The stretch goal will be lifecycle management, specifically graceful shutdown and timeouts. I’ve done this before in a similar tech stack, so I generally understand what’s going on. However, this is certainly an issue that needs to be handled carefully, since it has various moving parts like signal handling and managing the passage of time between tasks in the async runtime.
I don’t foresee any impediments.
I’ve made a lot of progress in terms of my process, although there is still room for improvement. Last semester, I used AI in a more conversational or consultation-based way, but struggled with perfectionism and wrote essentially all code manually. I don’t know if my perfectionism has gotten any better, but I’ve gotten more comfortable with letting AI actually write code. One key approach that has helped is continuously reaffirming that the overall goal to be optimized here is my learning. I’m still probably too pedantic about minor syntax concerns and obscure edge cases, and still catch myself spending too much time typing manually, but I’m at least over the fundamental hump of having AI generate the code. I think my process being unoptimized due to being too concerned about understanding and perfecting everything is better than erring in the opposite direction, but moving forward, I should continue to try to let go a little bit further.