๐Ÿ”— How I ship projects at big tech companies

Good post, although a hard one to read while reflecting on my last few weeks at work, and just feeling that I’ve been falling short in what it takes. ๐Ÿ˜”

Via this post, found on this BlogFlock.

Meeting at deadline is best. Second best is blowing past the deadline by such a wide margin that is was clear it was never going to happen. The worst by far is being close to meeting the deadline, yet it remains out of reach. Expectations are never recalibrated in those scenarios.

Spent the last few evenings continuing work on a Flutter-based RSS feed reader. This project is now further along then my previous attempts at doing this. I’m at the point where feeds and feeds items are being fetch from Feedbin and displayed in a list view:

Auto-generated description: A smartphone screen displays a list of feeds with titles like And now itโ€™s all this, App Defaults, and Articles on Jose M.
The beginning of the feed list
Auto-generated description: A screenshot of a social media app shows posts by Manton Reece discussing topics like media coverage, book covers, custom emojis, and Micro.blog features.
The feed item list. Title-less posts are to be fully supported, with a bulk of the summary shown in the list. Titled posts should have a smaller summary.

The aesthetics are taking a bit of a back seat in favour of functionality for now; I haven’t even changed the default accent colour. But the infrastructure is there: tapping a feed will bring up the entries for that feed. This is using named routes for navigation, and cubits for state management. It’s a bit more work upfront, but it does make for a neater codebase.

The biggest challenge so far was getting the actual reader view working. I hoping to use the webview plugin, but when I tried adding it, I ran into a bunch of Gradle errors. These were either class version errors or dependency errors, depending on what I tried to fix it (I didn’t get screenshots, sorry). I eventually stumbled upon this Flutter Gradle plugin migration guide, and following this, along with upgrading Java to OpenJDK 25, got Gradle working again.

But I was still getting build errors. The first couple were Gradle plugins com.android.application and org.jetbrains.kotlin.android that needed to be updated. Easy stuff. And then I got this error message:

Execution failed for task ':webview_flutter_android:compileDebugJavaWithJavac'.
> Could not resolve all files for configuration ':webview_flutter_android:androidJdkImage'.
   > Failed to transform core-for-system-modules.jar to match attributes {artifactType=_internal_android_jdk_image, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime}.
      > Execution failed for JdkImageTransform: /Users/leonmika/Library/Android/sdk/platforms/android-34/core-for-system-modules.jar.
         > Error while executing process /Users/leonmika/Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/jlink with arguments {--module-path /Users/leonmika/.gradle/caches/8.10.2/transforms/575ccd1a7426c0be21d9fe3a81898be3-05a021da-a1a7-409f-a30a-bba769b57371/transformed/output/temp/jmod --add-modules java.base --output /Users/leonmika/.gradle/caches/8.10.2/transforms/575ccd1a7426c0be21d9fe3a81898be3-05a021da-a1a7-409f-a30a-bba769b57371/transformed/output/jdkImage --disable-plugin system-modules}

Running a web search on the error revealed this Stack Overflow answer, which resolve it. There were still a few complaints about the the NDK version but after all that, the app finally launched with the web-viewer.

Auto-generated description: A smartphone screen displays a simple app interface with the title Read The Feed and placeholder text saying Content goes here.
The web-viewer, with a "hello world"-ish test HTML document

I still need to actually render the entry, plus style the HTML a bit. The immediate goal after this, once the reader view, is getting this on my phone to start playing with it. It’s just barebones for now, but I find that the sooner I can start using a project myself, the more likely I am to keep at it.

If you’ve ever been asked to decide the session duration for a work-based application, choose a time based on how long your users will be at work. The AWS session token I have last 8 hours, but I’m at work for 9: 8 hours of work plus 1 hour lunch break. Come the end of the day, if I’m still doing things in AWS, I’m always prompted to log in again.

Even better would be a session duration of 10 hours, just in case work goes a little long that day.

Well, it took 2 years, but the final step of decommissioning a domain is over: the domain has now expired. I feel bad for all the links I now broke (it was a domain that receive a little bit of traffic). I just hope all the 301 Permanent Redirects I was sending for 2 years did something.

Must be Theme Changing day, as I’ve made one last change that’s been on my wish-list for a while: the ability to page within the post screen themselves. This allows one to page through the entries without having to go back to the Archive section.

Auto-generated description: Two navigation buttons labeled Previous Post and Next Post are displayed on a light background.

Here’s the template to do that, which uses Tiny Theme’s micro-hooks:

<!-- layouts/partials/microhook-after-post.html -->

<nav class="paging">
  <ul>
  {{ if .PrevInSection }}
    {{ if eq .PrevInSection.Params.trip .Params.trip }}
      <li class="previous">
        <a href="{{.PrevInSection.Permalink}}">โฎ Previous Post</a>
      </li>
    {{ end }}
  {{ end }}
  {{ if .NextInSection }}
    {{ if eq .NextInSection.Params.trip .Params.trip }}
    <li class="next">      
      <a href="{{.NextInSection.Permalink}}">Next Post โฏ</a>
    </li>
    {{ end }}
  {{ end }}
  </ul>
</nav>

I also added a bit of CSS to space the links across the page:

nav.paging ul {
    display: flex;
    justify-content: space-between;
}

The only thing I’m unsure about is whether “Next Post” should appear on the right. It feels a little like it actually should be on the left, since the “Older Post” link in the entry list has an arrow pointing to the right, suggesting that time goes from right to left. Maybe if I removed the arrow from the “Older Post” link, the direction of time will become ambiguous and I can leave the post paging buttons where they are. Ah well, no time for that now. ๐Ÿ˜‰

One other thing I did was finally address how galleries were being rendered in RSS. If you use the Glightbox plugin, the titles and descriptions get stripped from the RSS. Or at least it does in Feedbin, where all the JavaScript gets remove and, thus, Glightbox doesn’t get a chance to initialise. I’m guessing the vast majority of RSS readers out there do likewise.

So I added an alternate shortcode template format which wraps the gallery image in a figure tag, and adds a figcaption containing the title or description if one exists. This means the gallery images get rendered as normal images in RSS. But I think this sacrifice is worth it if it means that titles and descriptions are preserved. I, for one, usually add description to gallery images, and it saddens me to see that those viewing the gallery in an RSS reader don’t get these.

Here’s the shortcode template in full, if anyone else is interested in adding this:

<!-- layouts/shortcodes/glightbox.xml -->

<figure>
<img src="{{ .Get "src" }}"
     {{ if .Get "alt" }}
        alt="{{ .Get "alt" }}" 
     {{ end }}
     {{ if .Get "title" }}
        title={{ .Get "title" }} 
     {{ end }} />
{{ if or (.Get "title") (.Get "description") }}
  <figcaption>
  {{ if .Get "title" }}
    <strong>{{ .Get "title" }} {{ if .Get "description" }} โ€” {{end}}</strong>
  {{ end }}
  {{ .Get "description" | default "" }}
  </figcaption>
{{end}}
</figure>

I’ve also raised it as an MR to the plugin itself. Hopefully it get’s merged and then it’s just a matter of updating the plugin.

A Summer Theme

Made a slight tweak to my blog’s theme today, to “celebrate” the start of summer.

I wanted a colour scheme that felt suitable for the season, which usually means hot, dry conditions. I went with one that uses yellow and brown as the primary colours. I suppose red would’ve been a more traditional representation of “hot”, but yellow felt like a better choice to invoke the sensation of dry vegetation. I did want to make it subtle though: it’s easy for a really saturated yellow to be quite garish, especially when used as a background.

My original idea was to use yellow as the link colour, but there wasn’t a good shade that worked well with a white background that had a decent contract1. So I pivoted, making the background yellow instead, and throwing in a brown for the link colour. That improved the contrast dramatically, and helped to make the theme a little more interesting.

One thing I did do was make it conditional to the data-theme attribute in the html tag, leaving me the option of adding a theme picker in the future. If you’re interested in the CSS, here it is:

:root[data-theme="summer"] {
    --background: #FFFEF5;
    --link: #895238;
    --link_visited: #895238;
}

@media (prefers-color-scheme: dark) {
    :root[data-theme="summer"] {
        --text: #f8f8f2;
        --link: #fce98a;
        --link_visited: #fce98a;
        --background: #30302a;
    }
}

I plan to keep this theme for the next three months, then look at changing it again when summer turns into autumn. It’s probably not a great colour scheme, as I generally don’t have the patience for making minute adjustments to get the style “just right”. I guess it follows on from my feeling of the season: I generally don’t like summer and I just want to get it over with. Perhaps doing something small like this is a way of enjoying it a little more.


  1. It was much easier for the dark theme. ↩︎

A grey and wet visit to Hastings today for lunch and coffee. Met someone at the cafe who bought his two cockatiels along with him, both in little harnesses.

A small building labeled "Fire Shed" is situated near a pier with numerous sailboats in the background on a cloudy day.

Dear Google,

If an address book has a contact with both a home and work phone number, please indicate which number is which in the Messages app. I just sent a birthday message to my sister’s work phone by mistake.

Something like this would be enough:

A message exchange shows a birthday greeting followed by a response clarifying the use of a work number. This is annotated with a red box around the heading, which has a 'Work' badge underneath the contact name. A sticky note below it has the message: note the 'Work' indicator below the contact name.

Regards,

lmika

โ€œHark! Is that the sound of singing angles, I hear?โ€

โ€œNo, itโ€™s just a Hyundai EV reversing.โ€

Hmm, not sure Iโ€™m ready for this reversing EV sound future weโ€™re facing.

Oh, it turns out it’s an older style of referencing targets and is no longer supposed to be used. That’s a shame.

A deprecated warning message indicates the need to replace the data-target attribute in a progress bar with an updated Stimulus.js format.

Huh, I was just adding a StimulusJS target attribute when Goland’s LLM suggested using a dot-based approach to reference the controller in the attribute value, instead of within the attribute name. I gave it a try and it worked.

HTML code snippet of a StimulusJS controller includes a file upload button and a progress bar, with a target attribute with the name 'data-target' and the value 'upload-file.progress'

Is referencing the target this way a new thing? I think I prefer it.

Agree with @manton here. I used to be quite religious about Test Driven Development, but I'm less so nowadays. For the simple stuff, it works great; but for anything larger, you know little about how your going to build something until after you build it. Only then should you lock it in with tests.

We might be seeing the end of the tunnel with our performance woes at work. I did some profiling with pprof this morning, and saw that a large amount of time was spent in context.Value(). Which is strange, given that this is just a way of retreving values being carried alongside context instances.

My initial suspicion was that tracing may have been involved. The tracing library weโ€™re using carries spans โ€” like method calls โ€” in the context. These spans eventually get offloaded to a a service like Jaeger for us to browse.

We never got tracing working for this service, so I suspect all these spans were building up somewhere. The service wasnโ€™t memory starved, but maybe the library was adding more and more values to the context โ€” which acts like a linked list โ€” and the service was just spending time traversing the list, looking for a values.

This is just speculation, and warrents further investigation, maybe (might be easier just to spend that effort getting tracing). But after we turned off tracing, we no longer saw the CPU rise to 100%. When we applied load, the CPU remained pretty constant at around 7%.

So itโ€™s a pretty large signal that tracing not being offloaded is somewhat involved.

Frustrating day today. The service I’m working on is just not performing. It starts off reasonably well, but then the CPU maxes out and performance degrades to 20%.

It may be the JWT generator, but why would performance degrade like that over time? It could be the garbage collector (this is a Go app). Maybe we’re allocating too many things on the heap? Or maybe we’re hitting some other throttled limit, making too many API requests. But I can’t see how that’ll max out the CPU. It’s not like it’s waiting on IO (or, at least, I can’t remember seeing it max out on IO).

Anyway, looks like another session with the profiler is in the cards.

So apparently the X’Trapolis trains have some form of battery. I saw one just drop its pantograph, yet the lights inside were kept on. I guess that makes sense, as there needs to be a way to raise its pantograph back up again.

I remember a time when I thought Gradle was the bee’s knees: “no XML, config written in Groovy, how awesome.” Now, it’s the most frustrating part of Android development.

A development console displays a Flutter project's debug output with warnings about deprecated plugin usage. Message reads: You are applying Flutter's app_plugin_loader Gradle plugin imperatively using the apply script method, which is deprecated and will be removed in a future release. Migrate to applying Gradle plugins with the declarative plugins block, followed by a URL
Yeah, I tried that. And it completely broke my build.

Got it working in the end by upgrading Java and the Android SDK, but golly it sapped a lot from me. Although, to be fair, I’m not how standard the Gradle build is for a typical Android project. I guess it’s better than when they were using Ant.

Anyway, kids: just use Maven. Work through the XML. It’s just a better build system.

๐Ÿง‘โ€๐Ÿ’ป New post on TIL Computer: Link: Probably Avoid Relying On Error Codes To Optimistically Insert In Postgres

Slippery when wet.

Auto-generated description: A wet floor caution sign stands in a tiled underground walkway with puddles on the floor.

Seriously, watch yourself when walking through that subway on a wet day. That tiled floor is treacherous.