• Looking at the core gRPC status codes this morning. There are 17 status codes in all, and most of them — like NOT_FOUND or PERMISSION_DENIED — are what you expect. I can see why those codes are listed there. They’re pretty common error conditions seen in most systems.

    But the code DATA_LOSS appears there as well:

    DATA_LOSS (15): Unrecoverable data loss or corruption.

    I’m a little curious as to why that error case was considered worthy enough to be given a code here. Hopefully not because it was frequent enough to warrant one.

  • Looking through my drafts last night to see if I could use one of them for my daily post. Found one that I wished I actually published at the time. Not because it was insightful or anything. It was just a record of what I did that day. But that’s sort of what this blog’s about in the end (as I need to keep reminding myself).

    P.S. I ended up publishing it with the original timestamp using Micro.blog’s scheduling feature. It’s super useful for publishing things with date-stamps in the past as well as the future. I use it all the time.

  • Spent some time closing off the Dynamo-Browse shortlist. I think I’ve got most of the big ticket items addressed. Here’s a brief update on each one:

    Fix the activity indicator that is sometimes not clearing when a long running task is finished.

    How long running tasks are dealt with has been completely overhauled. The previous implementation had many opportunities for race conditions, which was probably the cause of the activity indicator showing up when nothing was happening. I rewrote this using a dedicated goroutine for handling these tasks, and the event bus for sending events to the other areas of the app, including the UI layer. Updates and status changes are handled with mutexes and channels, and it just feels like better code as well.

    It will need some further testing, especially in real world use against a real DynamoDB database. We’ll see if this bug rears its unpleasant head once more.

    Fix a bug in which executing a query expression with just the sort key does nothing. I suspect this has something to do with the query planner somehow getting confused if the sort key is used but the partition key is not.

    Turns out that this was actually a problem with the “has prefix” operator. It was incorrectly determining that an expression of the form sort_key ^= "string" with no partition key could be executed as a query instead of a scan. Adding a check to see if the partition key also existed in the expression fixed the problem.

    Also made a number of other changes to the query expression. Added the ability to use indexed references, like this[1] or that["thing"]. This has been a long time coming so it’s good to see it implemented. Unfortuntly this only works reliably when a single level is used, so this[1][2] will result in an error. The cause of this is a bug in the Go SDK I’m using to produce the query expressions that are run against the database. If this becomes a problem I look at this again.

    I also realised that true and false were not treated as boolean literals, so I fixed that as well.

    Finally, the query planner now consider GSIs when it’s working out how to run a query expression. If the expression can be a query over a GSI, it will be executed as one. Given the types of queries I need to run, I’ll be finding this feature useful.

    Fix a bug where set default-limits returns a bad value.

    This was a pretty simple string conversion bug.

    Add a way to describe the table, i.e. show keys, indices, etc. This should also be made available to scripts. Add a way to “goto” a particular row, that is select rows just by entering the value of the partition and optionally the sort key.

    These I did not do. The reason is that they’ll make good candidates for scripts and it would be a good test to see if they can be written as one. I think the “goto” feature would be easy enough. I added the ability to get information about the current table in the script, and also for scripts to add new key bindings, so I don’t force any issues here.

    The table description would be trickier. There’s currently no real way to display a large block of text (except the status bar, but even there it’s a little awkward). So a full featured description might be difficult. But the information is there, at least to a degree, so maybe something showing the basics would work.

    Anyway, the plan now is to use this version for a while to test it out. Then cut a release and update the documentation. That’s a large enough task in and of itself, but I’d really like to get this finished so I can move onto something else.

  • With all the designs I’ve made for systems using the Stripe API that blew up in my face because of some undocumented edge-case, you would’ve though I’d internalise this by now, and remembered that the only real strategy for knowing that a design is viable is to actually test it.

    But no.

    And so here I am once again, trying to contort my design so that it’ll work with the Stripe API while trying to avoid making any dramatic changes. 🤦

    So, for next time: build a prototype, and use it to validate your hypothesis. Honestly, just do it. Spending those few hours of work now will save you the many hours of work down the line, when you find that you’ve hit some edge-case and you’ll have to go back to the drawing board.

    Just frickin’ prototype!

  • It’s Tuesday, I don’t shutdown my laptop during the week, and I only just now launched a terminal and IDE. Guess how much programming I did yesterday.

  • Whenever I read something about tech or music, a voice in my head starts saying things like I can do that, I can’t do that, I could’ve done that, I should’ve done that, I did do that, etc.

    I wish that voice just shut up. It’s debilitating hearing this when you’re just trying to learn something or appreciate someone else’s work.

    🙂

  • Less Consuming, More Creating

    Mike Crittenden posted a good quote from a random Hacker News commenter:

    Less consuming, more creating.
    Doesn’t matter what it is, doesn’t matter if it’s bad.

    This quote actually sums up this blog quite nicely. The first line explains why it came to exist. The second line describes how it continues to exist.

    Happy 1,000th post.

    Continue reading →

  • Ballarat Beer Festival 2023

    My friends and I returned to Ballarat today for the Beer Festival. It was another stunning day for it: sunny, mild, not too hot. Much like last year I took an earlier train to walk around Ballarat a little. Not much to report here: very little has changed. But I never see Ballarat so it’s good to walk around a little. My friends were on the train behind mine and I caught up with them when I boarded at Ballarat. We then made our way to Wendouree park for the festival.

    Continue reading →

  • Very hot today. Mercury hovering just under 40°C, with every chance that it may get hotter than that. But you know what? I rather it be hot today than tomorrow. Why? You’ll find out tomorrow. In the meantime… cheers! 🧊☕️

    A home-made ice coffee on a kitchen bench
  • 🔗 From Bing To Sydney

    Hmm, it’s hard not feeling a little unsettled after reading this Stratechery post. One thing’s for sure, I’m a bit more doubtful of the post I wrote two days ago.

  • Anyone making a software tool that converts times between time-zones, please let me enter the time-zone as an offset from UTC.

    Something that only accepts time-zone abbreviations or city names are problematic. For one thing, zone abbreviations are location specific. Dealing with technology mainly developed in the US, I’ve got into the habit of writing AEST when I want Australian Eastern Standard Time. But I wouldn’t bat an eyelid if I saw one of my compatriot use EST to mean the same thing. Is your tool smart enough to recognise this, or will it just default to US Eastern Standard Time?

    Now granted that’s one that’s got a work around. But let’s say I want to know the time on Low Howe Island. I’d probably use LHST for that, but does that mean “Lord Howe Standard Time” (UTC+10:30) or “Lord Howe Summer Time” (UTC+11:00)? Both of those abbreviate to LHST, and your tool will need to be smart enough to know the particular date and whether or not summer time is in effect. If you think you can handle that edge case, take a look at the list of time-zones abbreviations on Wikipedia to see how you’d be able to handle BST.

    What about city names? Yeah, city names might work, but you have to make sure your tool knows of every city out there. I’ve been trying to use Numi to convert from Melbourne time to Apia time. The docs seem to suggest that typing in 13:00 Melbourne time in Apia should work. But as far as I can tell, it doesn’t seem to recognise this as a time-zone conversion expression. It seems to give up and just give me 1:00 pm the answer, possiably because it doesn’t know about Apia1. I’m wondering if it even knows about Melbourne (I don’t know what each of the colours mean).

    Numi session with an attempt to convert 1:00 pm in Melbourne to Apia time, and the result is 1:00 pm when it should be 3:00 pm.

    And let’s not forget the issue of multiple cities having the same name. Melbourne could refer to Melbourne, Australia or Melbourne, FL, United States. I’d like to see how your tool handles Portland (keep in mind there’s a Portland in Australia as well).

    So, please. Make it easy on everyone, including yourself, and just recognise UTC±xx:xx. It would be so much easier and less ambigious if I could just to 13:00 UTC+11:00 to UTC+13:00. Or whatever, pick a syntax that works for you.

    And if you do have support for this, please make sure you document it somewhere.


    1. Apia is the capital of Samoa ↩︎

  • Ignoring Bard to Speak to Paulie

    So this happened today.

    Our team was testing the integration between two systems. The first system — let’s call it Bard — can be configured to make API calls directly to Stripe, or be configured to use the second system — let’s call it Paulie — to call Stripe on it’s behalf. Bard has a REST API that is used by the HTML front-end to handle user requests. Paulie is designed to be completely isolated from the front-end and has a simple gRPC API that Bard calls. Whether or not it Bard calls Paulie at all is determined by the value of an SSM parameter.

    Continue reading →

  • 🔗 ChatGPT clearly has a place

    I tried ChatGPT for the first time this morning. I needed a shell script which will downscale a bunch of JPEG images in a directory. I’m perfectly capable of writing one myself, but that would mean poking through the ImageMagick docs trying to remember which of the several zillion arguments is used to reduce the image size. Having one written for me by ChatGPT saved about 15 minutes of this (it wasn’t exactly what I wanted, I did need to tweak it a little).

    A ChatGPT session where I ask for a script that reduces the size of JPEG files in a directory.

    I don’t know what the future holds with AIs like this, and I acknowledge that it has had an effect on some peoples’ living (heck, it may have an effect on mine). But I really can’t deny the utility it provided this morning.

  • Flights and accomodation for the Europe trip booked. It’s been hanging around my to-do list for the last two months. Good to finally check that off.

  • I suspect, in a world where companies are replacing staff with AIs, that the organisations that choose to keep the humans on will have the competitive advantage. You can’t form a connection with a machine.

  • New Stuff Setup Weekend

    A bunch of new stuff I’ve bought has arrived recently and this is the weekend I finally get around to setting it up.

    New Furniture

    The largest one is a new couch. I’ve been sitting on a second-hand two seater that my parents gave me when I’ve moved out. It did the job but it was getting quite old and saggy, and I’ve been finding myself wanting to have something larger that I can lie across. So about six months ago, I bought a new couch. It was meant to come last December, but got delayed thanks to Covid-19 supply chain issues. But it finally arrived this Saturday.

    Continue reading →

  • Spotify Video Follow-up

    Some follow-up from my post about Spotify videos. I looked into this a little and from what I understand they’re not full videos but “short looping video clips that play during certain songs,” at least according to this website.

    So I guess my initial belief is incorrect. Spotify might have music videos (they’re a bunch of articles about them thinking about it in 2020-21) but this looks to be completely different.

    Furthermore, you can turn them off. They’re called “Canvas Video Clips”, and if you go into the preferences of the Android mobile app, sure enough there’s a switch for them.

    Continue reading →

  • I just realised there’s a downside to cross-posting my Micro.blog posts to Mastodon: I can’t use hashtags ironically anymore. Not that I’m in the habit of doing so, but the occasional one would be nice.

    Hmm, how to adapt? £thinking

  • Computers may have bested humans in Go but we still hold the advantage when it comes to Go. 😉

    (Although for how much longer is still an open question)

  • Toying with the idea of cancelling my Spotify subscription. There are a number of reasons for this, but one that really gets to me is the insistent need to show video when playing a song. And there’s no way to turn it off anywhere (I tried looking for one).

    I listen to music when I’m walking or driving or doing something that needs my visual attention. But even if I am in a position to stare at my phone, I don’t want to be watching music videos. So why is my bandwidth being wasted streaming a video when an MP3 will do?

    So obnoxious it borders on being offensive.

  • Trying out Keyboard Maestro to automate some niggly things I occasionally need to do. Got my first macro working, which converts a selected string FromCamelCase to UPPER_SNAKE_CASE.

    Screenshot of a Keyboard Maestro macro which converts the selected string from CamelCase to UPPER_SNAKE_CASE

    So far I’m impressed. Looking forward to finding other things I can automate away with this.

  • I don’t know what I need to do to get Swift Packages working.

    It never seems to work for me. The option to add dependencies are in the menu, but when I try to use them, they error out or cannot resolve the dependencies for some reason.

    This is in addition to not being able to see or edit “Package.swift” as a text file, which I thought was the whole thing with this.

    Is it the version of Xcode I’m using? Does it work for anyone outside of Apple? Libraries are being released with Swift Package support so it must work for someone.

  • Read my last post during lunch to see how well it read. Couldn’t get past the third paragraph without thinking: wow, this is really boring. Rewriting it helped a little, but it’s still rather dull. Maybe it’s the topic?

    In either case, it’s something I need to work on. 🧑‍💻

  • On Higher Order Functions In Go

    It’s a bit surprising that higher-order functions like map and filter have not caught on in Go.

    They seemed to have caught on quickly when they were added to Java. One of the long standing issues back then was the clunky and verbose approach to writing closures. Java 8 fixed this with the introduction of the lambda (the -> operator). Suddenly, what once took multiple lines of boilerplate could be done in a single expression. The underlying mechanism was still the same but the new syntax was enough to get people to use it (amongst other things, read on).

    Continue reading →

  • Spent the last week updating my travel blog a bit. Started writing about the the trips around the south pacific I took for work almost 10 years ago. I’ve been wanting to write about this for a while, before I forget most of it. I’m glad that I’ve finally got around to doing so.

  • A watched kettle never boils, and a watched clock will not get the train arriving sooner (sadly).

  • Making A Long Form Posts Category In Micro.blog

    I use the Categories feature of Micro.blog to organise the types of posts I make on this site. One of the categories I have on this blog is called Long Form Posts, which I use to file all the posts I have that have titles. This is done automatically, such that I don’t have to think about adding a post to this category once I’ve written it1.

    It’s a little hard to find the relevant features in Micro.blog to do this, but they’re there. Here’s how you can use them to make such a category on your Micro.blog blog.

    Continue reading →

  • I, Developer

    There was a bit of a discussion on Mastodon and various blogs about how best to call someone who writes code for fun or profit. I’ll spare you the prologue of how this discussion that has been going on since the start of the profession itself: I’m sure you’ve heard it all before. But hearing one of these terms today got me thinking about this, and I thought I’d say what my preferences are.

    Continue reading →

  • Pro tip: don’t have a sprint planning meeting with the hiccups. I’ve tried it today and it’s just didn’t work out.

  • Out walking my usual Sunday arvo. route. Perfect conditions for it as well.

  • Mahjong Score Card Device

    I’ve recently started playing Mahjong with my family. We’ve learnt how to play a couple of years ago and grown to like it a great deal. I’m not sure if you’re familiar with how the game is scored, and while it’s not complicated, there’s a lot of looking things up which can make scoring a little tedious. So my dad put together a Mahjong scoring tool in Excel. You enter what each player got at the end of a round — 2 exposed pungs of twos, 1 hidden kong of eights, and a pair of dragons, for example — and it will determine the scores of the round and add them to the running totals. It also tracks the winds of the players and the prevailing winds, which are mechanics that can affects how much a player can get during a round. The spreadsheet works quite well, but it does mean we need to keep a bulky laptop around whenever we play.

    Continue reading →

  • Tried doing some electronics this morning. Not much to show for it apart from some reading, designing, and driving to Jaycar to grab some components. This really is an activity where I’m still quite a novice.

  • OS/2 Dreaming

    I’ve been thinking of OS/2 recently. Yes, the ill fated OS that IBM built with Microsoft. Re-reading the Ars Technica write-up of it and listening to the Flashback episode again fills me with nostalgia.

    Truth is that a lot of my early experiences with computing began with OS/2. Dad was working somewhere that used it, and I had a chance to play with it whenever he bought his laptop home. We had a plain old DOS home computer as well but it wasn’t as powerful or exciting as the laptop as dad’s laptop. It also helped that the laptop had a colour screen.

    Continue reading →

  • Follow-up to my last post: you can turn off committing after conflict resolution in GoLand by clicking “Modify options” in the Merge dialog and selecting “Do not commit the merge result.” This should display the --no-commit flag.

    GoLand merge dialog with the no-commit option

    Ok, I admit it’s pretty close to how it works on the command line; although not when you have conflicts, and the only time I merge in GoLand instead of the command line is when I need to resolve conflicts (I prefer the diff/merge tools there). But to be fair to GoLand, it doesn’t know about my merging preferences.

  • I don’t understand code editors that think they know when to commit changes “better” than I do.

    GoLand is guilty of this. I just finished resolving merge conflicts, but instead of letting me make sure the resolved conflicts actually build and pass the test, GoLand just commits them as soon as I’ve finished picking the hunks I want to use. This means any fixes I need to make cannot go into the merge commit. That commit is now unstable.

    One could argue that this is the proper way to do things, that the merge commit should only contain conflict resolutions and nothing else. I don’t agree. I’m bound to make mistakes while resolving conflict, and I want to make sure what I’m committing is actually working code. It probably doesn’t matter in the grand scheme of things, and it wouldn’t be the first time I make a commit with dodgy code. But I’d like to reduce the number of times that happens if I possibly can.

    Besides, conflicts in Go imports or module versions I can usually fixed by running tools. I tend to resolve these conflicts quickly, expecting to get errors and duplicates that I can fix with a couple of commands (they usually need to be formatted anyway). I can’t do this if the code editor decides when to actually commit the changes.

    Stage the resolved conflicts all you like, but let me actually commit them when I say so.

  • This hollow is hot property at the moment. It was occupied by a couple of kookaburra chicks about a month ago. They’ve since flown the nest. Now a pair of rainbow lorikeets are interested in it.

    Two rainbow lorikeets outside a hollow in a gum tree
  • It kills me that Pinboard doesn’t automatically set the title of a bookmark if you add one without it. So easy to fetch the page and get it from there. It can be a setting if privacy/costs are a concern. But really, having this feature would be a massive usability improvement.

  • Premature abstraction is the root of unnecessary rework.

  • Might just have to accept that the way I manage links to posts of interest is not perfect. There might be some room for improvement — something that polls Pinboard occasionally and posts any new links from there somewhere — but a wholesale replacement is probably not a good idea.

  • A reminder to myself that the only way to get a blog post out there that you’re happy with is get a blog post out there that you’re not happy with. Classic case of learning by shipping. And I think you need to actually need see it all the way through to publishing it. I’m not convinced that you’ll get the full benefit if you just leave the post half-finished in your drafts folder.