Showing 6 posts
Initial versions of the EndBASIC Service, and therefore initial versions of EndTRACKER, used dynamic dispatch to support abstract definitions of system services such as the database they talk to and the clock they use. This looked like a bunch of Arc objects passed around and was done to support extremely fast unit testing. When I generalized the core logic of these services into the III-IV framework, I decided to experiment with a switch to static dispatch. The rationale was that using static dispatch better aligns with the design of well-regarded crates in the Rust ecosystem, and also because I wanted to avoid unnecessary runtime costs in the foundational pieces of my web services. Let me tell you that this decision was a huge mistake and that the experiment has utterly failed. Using static dispatch has been a constant source of frustration due to the difficulty in passing types around and reasoning about trait bounds. The situation had gotten so bad that I dreaded adding new functionality to my services whenever a change to a statically-typed struct was needed, because that meant adding yet another type parameter and plumbing it through tens of source files. In lieu of the difficulties, which eventually turned into blockers to implementing new features, I made the choice of going back to dynamic dispatch. The goal was to gain ergonomics at the expense of a supposedly-negligible runtime cost. Let me tell you about the problems I faced, the refactoring journey, and some measurements I gathered after the rewrite.
One of the things I'm most proud of the Rust web services I have written is how I can run their tests with zero setup and within milliseconds, all while making me confident that "main" can always be shipped to production. I've previously touched upon how this all works in other articles, but it's time for a deep dive. To make things specific, I'll be describing the testing infrastructure of EndTRACKER, the EndBASIC Service, and the sample key/value store app of III-IV. These services are all structured in three separate layers, and I'll be covering the testing strategy for each of them.
A couple of posts ago, I described why I built custom email subscriptions for this blog. I briefly mentioned that there is new automation that scrapes the RSS feed and sends new post notifications to you all. Today, it’s time to look into how this all works and how this is based on a new persistent task queuing service in Rust. The queue handles tasks to periodically scrape the RSS feed and schedule emails, all with various quota enforcers and retry policies in place. Read on for the design requirements and constraints of the task queue, how the client and worker Rust APIs look like, and how this all can be made to work inside the Azure Functions serverless runtime for minimal deployment hassle and cost.
Fellow readers! The radio silence for the last two months has an explanation. I’ve been busy creating a custom email subscription service for this blog, all so that you can be notified about new posts without the noise added by intermediaries. This feature is built into a little Rust web service that already offered analytics, page comments and more, and that can be potentially integrated into arbitrary static websites. Read on for what was involved, stay tuned for a deep dive on the internals, and… upfront apologies if this first email does the wrong thing!
Just a couple of weeks ago, I described my home-grown analytics service for this site. Today, I’m here to describe a couple of related updates: namely, the support for comments and the complete removal of client-side fingerprinting.
One thing that had been bothering me about my websites—including this blog, but especially when launching https://www.endbasic.dev/ just a few months ago—was this: uBlock showing a warning that it blocked a tracker on the EndBASIC site. A tracking warning. uBlock complained that my properties had one tracker. And it’s true they had just one: it was Google Analytics, or GA for short. GA is the de-facto standard for web analytics: it is extremely powerful and ubiquitous.