In my last post about the ECS migration, I complained about type discoverability with ECS compared to OO. I had already started to experiment with compile-time contract concepts but wasn't sure if it was just object-oriented thinking dying slowly. I now have something that makes me decently happy, but it may still make true ECS devotee's hair stand on end. I'd be curious to hear if and how this might be wrong-headed. Anyway, here's some compile time contracts for Archetypes using Arch-ECS
I've been using Daniel Greenheck's CitySim.js as a sandbox for experimenting with simulation architecture. Not to improve or comment on Daniel's design — his goals are unrelated to mine — but because it gives me a fully-functioning city sim with a Three.js presentation layer I can work with, and it's a stepping stone for my other city sim projects.
I've been making modifications to this project on and off for a while now. The motivation for writing about it now is that the transition from Object-Oriented to ECS thinking has been the most interesting (to me) of my experiments in this code base. But I should cover some ground before getting to the actual topic. In brief: I took Daniel's code, spent some effort separating the simulation from the presentation, moved the simulation to a node.js server using the CQRS pattern, then ported that server from Node.js to C# using Wolverine for the CQRS plumbing. This post is about my latest refactoring — migrating from a per-object, class-hierarchy simulation to an Entity Component Systems architecture — and what that actually involved.
I grew up on 80s arcade shooters. Asteroids, Space Invaders, Galaxian, Scramble, Defender and others all consumed an
inordinate number of quarters, basically whatever allowance I had. Of all of them the one that left the most lasting
impression was Zaxxon. The 1982 Sega arcade cabinet — and later its ports to whatever home computer you could convince
your parents to buy — was unlike anything else at the time. An isometric scrolling shooter where you had to manage
altitude to fly through gaps in walls, dodge missiles, and bomb ground targets. The shadow beneath your ship was your
only depth cue. It was brutal, beautiful, and unique for its era. Mind you I always sucked at it, but I could
watch the attract screen all day.
So when I was looking for a bite-sized project to try Claude Code on, Zaxxon immediately came to mind. It was something
I could easily do myself, which gave me confidence that I would be in a good position to judge the output that Claude
produced.
The result is Voxxon — a browser-based
isometric scroller in Three.js with voxel explosions, a leaderboard, a boss battle, and more features than I
originally planned.
First post in almost two years and what is it about? Refactoring my mastodon comment system yet again, this time turning it into a Digital Ocean Function. I know, I know, wasn't it essentially a function with AWS Lambda originally? Yes, it was, but I converted it to ECS because of the NAT and elastic IP requirement.
That limitation, it turns out, does not apply to DO Functions. They have public internet access out of the box at no extra cost. So it's more economical than either my AWS Lambda or AWS ECS approaches.
Of course, right after that I posted one more brief article and then went blog silent, using my mastodon for bite sized updates instead. But that's another story.
Venturing back into C# for the first time in a long time. I'm only 5 minutes in and already felt
compelled to create a new utility class.
Essentially I'm adding an ASP.NET Web API to a daemon process, which requires that the REST API
can get exclusive access to some daemon in-memory state. Since I'm building everything around
async/await, I went looking for the async equivalent of the traditional lock, only to not find
one. From what I could gather, the recommendation is to build one around SemaphoreSlim. After
using that explicitly, I was really uncomfortable with having to make sure that I a) released the
semaphore and b) did it in a try/finally.
Well, damn it. Here I am procrastinating on my archviz project with a server side project. I am an infrastructure engineer at heart, so anything server related will always pull at me harder than any other project. So right after writing the Future Work section in my last post, I started looking more closely at Daniel's approach to using mastodon for comments. The part that scratched my server-side geek itch was his chicken-egg problem forcing the workflow:
create post
create toot
update post with toot id
I just want to publish my post, have a matching toot automatically be generated and have the original post be able to discover the corresponding toot_id. I want to keep my blog static and don't really want to add this into the build pipeline, so what I need is a web service that will lazy publish the toot and return the toot_id for a given URL.
For the last ~10 years, I hosted everything on a single EC2 instance behind an ElasticIP. A couple of wordpress sites, some static sites, a couple of node apps, all through nginx. Deploy was git checkouts and some shell scripting. After having my server taken over once because of a wordpress vulnerability, I now ran all my wordpress with read-only files, so that felt decent. Just had to make them read/write for version and plugin updates. Mind you all this is very low traffic hobby sites.
But I really wanted to get to immutable deploys. Run these sites as separate docker containers I could more easily test locally and deploy was a replace. I converted one WP site to docker and figured out how to run it with ECS. Then last month I set out to decommission the EC2 and convert everything left.
My WP deploys were using the default WP container as a base, but claassen.net was structured with the blog as a
sub-directory and a bunch of static site elsewhere. I considered reconfiguring the container to serve the existing
hierarchy through its nginx, but in the 10 years of not posting, my tastes for authoring had moved distinctly from WYSIWYG to markdown and if I was going to get back to blogging, I wanted to go static. I briefly
considered jekyll, but had been using MkDocs at
work and really liked it, plus I am far more fluent in python than ruby. Some brief googling later, I
found Material for MkDocs which comes out of the box with blogging
support and with LoneKorean's WordPress Export to Markdown
I was well on my way.
My current go-to deployment strategy is AWS Elastic Container Service (ECS) using Fargate behind an Application Load Balancer (ALB). Each site is its own stateless docker container persisting dynamic data in RDS and/or S3. When I make a change, I build the new container, push it to ECR, create a new task revision and ECS deploys the site for me.
I've now set this up a couple of times and each time I struggle to recollect all the steps along the way, so it's high time I write it down so that I can look it up next time. And now that I understand this a bit better, I was also able to consolidate my infrastructure, since my original approach wasn't necessarily the most cost-efficient setup.
Aside from remembering/reverse engineering all the pieces needed, the part I always got stuck on was the apparent catch-22 of a load balancer wanting a target group, a target group wanting an IP, while the ECS Service wants to set up a load balancer before providing said IP.
Learning how to use ECS tasks to run some cron jobs has been an opaque journey to say the least.
I knew my TaskDefinition was fine, because my server was running, but I wanted to use that same definition with a different container command and schedule its execution for housekeeping tasks.
I started with creating an EventBridge schedule, which seemed straight forward enough. But as soon as I created it I was puzzled that there didn't seem to be a way to trigger it for testing nor was there any kind of information on whether or not the last invocation had happened and succeeded.