It turns out that having a web app update its own code is really hard
Attempt #1: Try doing it in a single long HTTP call even though it’s a 3-5-minute process
Quickly realized this is dumb because nginx times out the call, and lots of other things would probably time out a 3 minute HTTP call.
Attempt #2: Make it asynchronous, but keep track of the background job using a global variable (I know it’s hacky!).
Part of the update process is restarting the TinyPilot web server, which loses the global state.
Attempt #3: Instead of a global variable, store state in a file.
Worked, but on service restart the thread performing the update gets restarted, so it never records completion.
Attempt #4: Instead of a background thread, use a background process.
Still didn’t work, process gets killed when the parent process dies.
That’s weird, shouldn’t the child process stay alive?
After lots of digging, I realized the child process was dying not due to regular OS process management but due to systemd killing all children on service restart.
Attempt #5: Instead of a background process, start a new one-shot systemd service
Updated all my documentation to point to the support forum instead of sending me a private email (thought private email is still an option)
I’m really liking this solution!
Every time I respond to a support question via private email, I feel like useful information is being trapped in my inbox.
When I answer a question on the support forum, it feels like I’m making an investment in something that will pay dividends over time as other users encounter the same issue.
Shoutout to TalkYard. It’s an open source forum similar to Discourse, but it’s an indie developer, priced much more affordably, and I like the interface better.
Tried to set up an affiliate program, but it turns out every Shopify solution requires you to hand over your entire customer database to an affiliate marketing company.
Reviewed design doc for potential rack-mounted future version of TinyPilot
I used to put my unit test files in a separate tests folder with a subfolder structure that mirrored my production code.
My new solution is to put tests alongside production files and change the naming so that it’s foo.py and foo_test.py rather than test_foo.py even though the latter is standard. But the foo_test.py way, the test and production files appear adjacent to each other in most file views, so I am cautiously bucking standards there.
Updated logic for updating the sudoers file so that it can’t generate duplicate lines or corrupt the file.
Added a check to the website repo for whitespace violations
I don’t really use any budgeting / personal finance apps, but I’m considering starting with personal accounting to see if it works well enough to use on my business.
I dislike every bookkeeping SaaS I’ve ever tried, so the idea of an accounting system that’s scriptable and under source control really appeals to me.
Here’s my progression:
ledger-cli: Okay, I’ll start with the oldest and presumably most mature product. Hmm, a lot of things about this don’t make sense, like it doesn’t seem to lend itself very well to automation. And why is a text-processing app written in C++?
beancount: Okay, Python-based. That makes more sense! And it has a slick web interface, yay! But all the instructions about automating imports are either incomplete or broken.
hledger: Okay, Haskell-based? I don’t see myself ever learning Haskell, but maybe this app makes it so I don’t have to. Finally, a reasonable quickstart guide.
Back to beancount because a friend sent me some example scripts he uses, so I’m going to try to work from those.