This week like many of the next ones has been focused on building a solid foundation and also cementing in decisions that need to be made that shape the vision of ncog.link.
What got done
This task mostly was porting code that I had written for Cosmic Cantina and Cosmic Verge. The client authentication needs to be updated when I start working on the game client again, but I’m liking how the system is set up.
As I was finishing up work on the previous task, I knew I needed to make it so that the WebSocket API could be used without being authenticated, and purposely avoid storing any cookie-esque information until the user has consented. As I’ve said in the past, I’m not out to maximize dollars, so I am perfectly happy to allow anonymous viewers on the website.
Upon attempting to sign up or log in, you will first be required to consent before you can initiate authentication.
Fixed my broken async/await code
On Tuesday, I ended my day with the conclusion that DigitalOcean’s load balancers weren’t able to support WebSockets natively. I reached this conclusion after seeing each time my socket upgrade happened, the container would stop accepting new connections.
I did a live-stream on Wednesday morning where I started out setting up the CloudFormation. In the midst of my Tuesday night frustrations, I realized that AWS’s Fargate pricing had been reduced enough that it made it very attractive compared to the costs associated with running Kubernetes. The only negative experiences I had with ECS were all due to the management of the ECS instances themselves, so the idea of not needing to worry about that won me over. Here’s the current CloudFormation.
Unfortunately, after getting this all deployed, I realized I was experiencing the same WebSocket hang issue. I set to try to reproduce it locally, and I discovered if I hardcoded Tokio to only use 1 worker thread, I could reproduce my hang locally. It only took a few minutes to realize the issue was utilizing Crossbeam unsafely within async code.
For anyone stumbling across this, if you’re using Crossbeam channels inside of async code, you need to be aware that those channels do not notify the async Runtime properly of blocking conditions. The easy fix is: if you’re using async code, use an async channel. I personally switched to Tokio’s unbounded_channel(), and it solved my problem immediately.
I did not go back and figure out if DigitalOcean’s load balancers would work or not. While my total spend on AWS right now is a little more than what I was spending on DigitalOcean, it’s fairly comparable, and as I scale up the price difference should mostly be mitigated. As I finish getting a full picture of what the deployed architecture will look like, I’ll happily do a deeper dive into how it’s all set up. Right now things are too new to know for sure if I won’t replace them as I test and scale more.
In terms of the web app, I’m wanting to start working on asset management. For the game client, I have two competing visions right now: 1) Integrate iced into my custom game engine Kludgine or 2) drop my game engine entirely and adopt coffee.
I had abandoned coffee as an approach for myself a while back when I did some performance tests on a simple game I had just ported from three-rs. Ultimately my journey led me to write my own little library which I’m really happy with.
Writing a UI library is a lot of work, especially if you want to support text input. While coffee right now doesn’t utilize iced yet, that work will eventually happen. Or, if I want to keep going with my engine, I can integrate iced into it.
The only real downside I can think of by using Iced instead of my own custom UI engine is that text rendering wouldn’t match. For the vision of ncog, I’m not sure that matters.
Speaking of the vision of ncog, as many people have been asking me, what exactly is it that I’m building? Well, that’s going to be a major focus for me next week. I’m going to try to spend a bit of time each day working on building a list of features and functionality I want in a v1 and try to organize some sort of roadmap.
Because this is a passion project first and foremost, I’m not going to be putting any hard deadlines on any specific milestones. My goal is to give a written update every Friday-ish, and in the process of writing that, I will not only reflect on what I did in the past week but also try to figure out the main goal for the next week.