I'm a software person at Prodigy Education. I'm also into Pizza & Bread.

My kiddo is convinced that because his school buys Dell computers, “they are the best computers”. It’s the first time I feel I’ve seriously failed as a parent.

I can’t believe that weekly IAP is still a thing. Are there any non-scam apps where this is a real requirement?

What FastMail really needs is a button that finds the unsubscribe link in an email and clicks it for you.

Scale to Zero with Fly.io Machines

 ·  Permalink

I’ve written a bunch of hobby apps over time that I use to keep my life moving forward. I’ve got some small side projects, like http.ist and Lemur that need web hosting. I also have utility apps that filter podcasts from podcast feeds, truncate my RSS news, or show me the swimming schedule for my local pool (their website was terrible).

I’ve been managing a Kubernetes cluster on DigitalOcean for this, but it feels like massive overkill in cost and resources. As an alternative, I’ve been looking at Fly.io, a Heroku-like PasS. Fly has been great for an easy single-command deployment.

In the past few months, Fly has started releasing the next generation of their platform: Fly Machines. They’re lightweight Firecracker VMs that boot quickly and are cheap to run. Fly Machines will eventually be used to provide all new features for Fly’s central app hosting service, but at the moment they don’t have all the bells-and-whistles niceties of Fly’s general development platform. I’m sure this will change over time. But, we can take advantage of them now with a few simple commands.

What’s powerful about Fly Machines today is that we can scale them down to zero and then save on cost while they’re idle. When a request comes in, they can scale up in roughly 300ms, serve traffic and then scale back down again. This makes them an excellent fit for hobby apps.

Let’s look at a sample app and how we’d do this with Fly.

First, you need to write your app. I’ve written cookiemonster that just yells “Cookie!” when you visit it. For Fly to scale the service down when idle, it looks for cases where the app has exited with a status code of 0. If the exit code is anything other than 0, Fly will assume that the app has crashed and will restart it. This is great, because the application developer has total control of when to mark the app as idle and shut it down.

To scale to zero in Node, it might look like this:

const express = require("express");
const app = express();

let lastRequest = Date.now();

app.get("/", (req, res) => {
  lastRequest = Date.now();
  res.send("Cookie!");
});

app.listen(process.env.PORT);

setInterval(() => {
  const oneMinute = 1000 * 60;
  if (Date.now() - lastRequest > oneMinute) {
    console.log("No more cookies.");
    process.exit(0);
  }
}, 1000 * 60 * 2);

If no one has made a request in the last two minutes, our setInterval check will detect it and exit the app. This can be improved with stuff like middleware, but that’s the general idea.

Deploying on Fly

To deploy this on Fly Machines, we can’t use the normal Fly.io steps (at least not yet, I’m sure it’s coming soon).

Instead we’ll do the following:

flyctl apps create cookiemonster --machines

This step creates an app “container” that holds our Fly Machine. It’s what you’ll see in the Fly.io dashboard.

By default, if you create an app with the above commands, it won’t have an IP address (and since these are web applications, we need them to have a public ip). So, we’ll run the following:

flyctl ips allocate-v4 -a cookiemonster
flyctl ips allocate-v6 -a cookiemonster

Then to deploy the app, we’ll run the following:

fly machine run . --app cookiemonster --port 443:3000/tcp:tls

This command does the heavy lifting. It will:

  • Look for a Dockerfile in the local directory
  • Build a docker image using a remote builder (you don’t even need Docker running locally)
  • Deploy the image to the image registry
  • Create a Fly Machine and host it in the cookiemonster app.
  • It’ll also open the external port 443 on the app to point at 3000 on the Fly Machine. If you need to handle non-https traffic, you’ll also want to do this for port 80.

When you run this command, it’ll give you back an id for the Fly Machine that it creates. You’ll need this to make changes (like pushing updates). If you lose it, it’s in the Fly.io dashboard inside your app under “Machines”.

When you want to update the app image, you can run:

fly machine update e148e453be6e89 --dockerfile Dockerfile

This will build the docker image again, push it, and then update the Fly Machine. This step is also really easy to add to CI pipelines.

If you want to view logs to watch the app boot or shut down, you can run:

flyctl logs --app cookiemonster

It will show the steps of the machine reserving resources, booting, and the stout of the app. When the app exits, it’ll helpfully report: “machine exited with exit code 0, not restarting”.

Cron Tasks

For cron tasks, you can also schedule Fly machines to wake up and run (hourly, daily, or monthly):

flyctl machine update e148e453be6e89 --schedule daily

Cron tasks don’t need the IP steps above. They’ll wake themselves up on the schedule, run their code, and then suspend.

Happy cheap hosting!

I’ve been looking for a replacement for Dash for documentation for a long time and just discovered devdocs.io. Where has this been?! It seems great!

I don’t want to jinx Twitter downtime, and I hope everything turns out ok, but… should somebody go buy some lettuce? Can it beat the lettuce? Edit: Someone did it.

It’s sad watching talented Twitter engineers and designers with years of tenure be squeezed out the door. I did not always agree with Twitter’s product design but there was some exceptional engineering. I hope they find a good home that respects their contributions.

Paw, my favourite mac API tool was bought by RapidAPI. They defoxified the dock icon, which just makes me sad. Luckily, they knew I was going to complain about this, so there’s a setting in Preferences to change it back! Phew!

Old Paw Icon of a Fox New Boring RapidAPI Icon

Of course, my kiddo’s school is going remote again (CUPE strike). I’m so ready for a year where we don’t have to do this to him. He doesn’t learn as well through a screen (except when watching Minecraft videos on YouTube).

I need a bell that I can ring for every time AWS signs me into the wrong region and I freak out because all of production is gone.

The Places of Mastodon

 ·  Permalink

I’ve spent a few days diving into Mastodon and the ActivityPub Fediverse. It’s new to me, but so far there’s a lot I like about it.

I’m one of those old people who are still mourning the loss of blogs. The internet moved onto Twitter, but I’ve always valued having my own place online to write, think, discuss, and archive my thoughts (this website has existed in some form since 2001). In the past few years, I’ve been using Micro.blog to bridge my blog with the world of Twitter by cross-posting (I like and recommend it).

Domain names are really powerful. They communicate something more than just where your content lives: the brand, identity, quality, values, or principles of your content. It’s where you’re coming from. When I write something at benjohnson.ca you know it’s just me. If I were writing from nytimes.com or gawker.com my writing would land a little differently (for better, or for worse).

This makes me fascinated by the power of Mastodon communities. On Twitter, your handle doesn’t communicate a dimension of place. Sure, there’s a verified badge (or… there was) and there are the eggs, but when you’re writing on Twitter you’re coming from Twitter — there’s no defined community or place behind you.

With Mastodon, you and your writing come from somewhere. That could be from a huge general community (@example@mastodon.social), a niche community (@example@spacelovers.up ), a personal domain (@elon@musk.com), a corporate entity (@maggie@nytimes.com), or some awful exclusive cryptobro haunt where you need to show your apes at the door to join (@bro@ohnomyapes.com).

If you had told me that a lot of people in 2022 would be moving to a social network based on a W3C standards-based federation protocol I would not have believed you. And I doubt everyone is going to jump ship from Twitter to Mastodon.

But, I’m having so much fun seeing a variety of domain names on the internet again.

Any politician who believes that daylight saving time is a good idea is welcome to come live with my 7-year-old this week. He woke up at 4am.

Someone needs to make a box that can bleep selected language so that I can show my kiddo all these movies he’s not old enough to see yet.

Kaleidoscope.app is expensive but is so worth it. There’s so many cases where a nice diff tool comes in handy. It’s one of those developer tools that pays dividends.

Introducing RenamerThing

 ·  Permalink

I’ve been a devoted “Paperless” person since 2012. I first got started with the ideas in David Sparks’ Paperless book, and I’ve grown my systems and practice from there.

The goal is that all the documents I might need are digital, organized, and findable. And all the paper is shredded and out of my life (and house).

For every document that needs safekeeping, my process roughly looks like this:

  • I use a ScanSnap scanner to scan to an OCR’d PDF in a folder called “Action”.
  • I shred the paper. This fills me with glee.
  • Hazel detects the new file, renames it, and moves it to the proper folder based on its contents, if it can.
  • For all the files left that Hazel can’t handle automatically, I manually rename and move them.

This last step is annoying. In a scanning and shredding session I might have twenty or thirty files left over to rename. I have to look at the contents of each file and rename based on my naming scheme. I’m currently executing a will, which involves a lot of paper, so this problem has come up more often than normal.

I wrote an app to scratch this very particular itch.

RenamerThing is stupidly simple. Given a folder, it’ll list all the files in the folder. When you select one, it’ll show a QuickLook view of the file (the contents) and there’s a bar at the top to give the file a new name. There’s also some shortcuts for prefixing with dates.

It’s on the Mac App Store for free. I might consider adding more to it in the future, but consider this a minimally useful version. That said, I have no idea if this is useful to anyone else, but it was driving me nuts, so I hope maybe this can help someone else too.

RenamerThing Screenshot

It’s shocking to me how much better Hacking With Swift is than Apple’s own documentation.

I asked my kiddo what he wants to do this weekend and he says he wants to make a movie and get a Netflix deal. Do I know anyone at Netflix that can hook a 6-year-old up?

Campbell Scott playing Tim Cook was the best thing about Jurassic World: Dominion.

Arduino

 ·  Permalink

I’m years late to this party, but the Arduino is so cool.

I’m a software person. I have almost no hardware experience outside of a high school class decades ago where we built hardware logic gates.

But, my kiddo has been falling down the Ghostbusters rabbit hole and he really wanted to make a ghost trap with blinking lights, sounds, and doors that open. It sounded like a perfect excuse to learn some basic electronics.

I bought the Arduino Starter Kit for like $100 CDN and it came with:

  • A microcontroller
  • LEDs to blink
  • Piezoelectric buzzer for beeping
  • A servo to open the ghost trap (naturally)
  • Wires, resistors, LCD screens, and lots more

It also came with an amazing starter manual that walks you through several projects to gain understanding of the various components in the kit. There’s even YouTube videos if you want a more visual walkthrough.

The Arduino has an IDE for uploading code to the microcontroller. The language is it’s C/C++ with a really simple API for controlling the various pins on the board.

In about an hour we had figured out how to have blinking lights and beeping sounds in response to a button press. I’m really excited to see how impressive of a ghost trap we can build.

My software career has been writing code that runs on servers or in browsers. I have some empathy for the hardware, especially when I do things that tax it. But, there’s something tangibly different about code written for a server in the cloud versus code on the Arduino. It’s addicting to see your software change something in the physical world. I really recommend it to other software people.