https://pine32.be - © pine32.be 2025
Welcome! - 103 total posts. [RSS]
A Funny little cycle 2.0 [LATEST]


Search 103 posts with 45 unique tags


#1757190021


[ mb_dev | golang ]

I recently updated the mb container image. It’s now just 4.91 MB (compressed), down from the previous 8.4 MB. This was possible by moving from an Alpine based container to a from scratch container. Go compiles to a static binary if you don’t need CGO, but I was using CGO because I needed some libc (musl/gnu). The next step was switching to a different SQLite driver, since that was my only C dependency.

There are several pure Go SQLite drivers, some are full rewrites in Go, while others are C code transpiled to Go. The solution I chose is ncruces/go-sqlite3, which compiles the entire SQLite project to WebAssembly and runs it in wazero, a zero dependency wasm runtime for Go. This way, we’re still running C code but without linking it, so no CGO.

I haven’t tested performance yet, but it seems fine so far. I’m planning to create a test suite using k6 for both functional and load testing.

There’s also some room for further size improvements. The default SQLite wasm binary includes all optional extensions, but I don’t need all of them (just math), so building a custom binary could shrink the image even more.

#1745864702


[ mb_dev ]

Of course, just when I say that my Spotify scraper hasn’t broken yet, it breaks. Luckily, it was just a small fix, but still. I also got the Navidrome embeds working, only 185 lines of code added (excluding the codegen). It only took a couple of hours. This should help for the meantime while I work on the custom music library management tool.

Cover Art
DEUTSCHLAND (Nedaj Edit)
Nedaj

#1745526310


[ mb_dev ]

Looking back, I’m really happy that I used web scraping for my Spotify embeds, seems to be quite resilient. This post has a track that doesn’t work on Spotify anymore, yet the embed still works fine. This isn’t a guarantee though, one day it will break, but not today. That’s why I am thinking about downloading all Spotify assets, so if it works now, it’ll work forever. It always feels hard to add these kinds of things while trying to stay minimalistic… maybe I should.

I am still looking for another way to integrate some kind of music embed. Maybe with Navidrome, since I’m currently using that for my ever-growing offline music library. I could share a track and then scrape that share to make an embed, that would work the same way Spotify works for now. Would work with a minimal amount of code, which aligns with the philosophy of this blog. But there are two small problems with this: having a full-length song publicly available (basically illegal distribution) and It depends on the Navidrome server and that specific share never going down. I could make the share low quality so people wont download it, but this is not a perfect fix.

This is running form a share on my Navidrome instance, it works: (KLOUD - DEFECT)

Another solution is using a custom music library management tool (which I am planning on making, soon™) that exports a music snippet to be upload in the media management of MB (automatically or manually) and a piece of html that will become the “embed”. I could already do this now manually, but I want to keep posts low-friction and this would help. It’s an almost perfect solution, no changes for MB and none of the Navidrome problems.

But a lot of code is needed for that music library management tool first. So it won’t be soon, while I could bang out the Navidrome solution in an evening or two. Maybe I should first make MB download all Spotify assets to lock them in place forever (I know it’s against the TOS but IDC). Still, it would increase the complexity of MB. It can’t be perfect, but what’s more important… I am going to download them, can’t trust Spotify with anything.

#1739535870


[ mb_dev ]

1 Year of MB!!

The first post was on 04/02/2024, missed the anniversary but better late than never. My goal was to make 1 post per week. I have made 70 posts this year (not including this one). So it looks like I hit my goal on average, but it was not really consistent, so that could be better. Nevertheless the goal of this blog was to make posting as easy as possible and I think it succeeded in that manner.

Development has slowed down but I still have some plans to add things like syntax highlighting for code blocks. There is nothing that I am missing at the moment, only some small nice-to-haves. I also want to keep it small, so I am keeping feature creep in check.

#1731920421


[ mb_dev ]

Got my first contribution and fork on this project. Happy to see his version deployed and taking on his own look. This project was made to be forked, I hope more people follow suit.

Hi Tim o/

#1722283789


[ mb_dev ]

So… this regex broke my site… Because it is a ‘Youtube URL’ but is has no ID so it breaks things and panics. I should really learn regex. But not now, hotfix for the win.

faulty regex screenshot

#1715288892


[ mb_dev | webdev ]

Finally added cache busting to mb. I should have done this long before but I only learned this technique recently. For some reason I never wondered how bigger sites did this.

For those who don’t know what cache busting is. It’s a technique used to force a web browser to download the latest version of a static file (css, img, …) instead of using a cached version. This is done by making every version of a file have a different and unique name, so the browser won’t recognize the updated file and will fetch it from the server. I have done this by adding a hash of the file to the filename, for example main-ad5d104a4a86.css.

With every version being a unique file we can update the Cache-Control header.

Cache-Control: public, max-age=31536000, immutable

This the most aggressive caching that you can configure, it tells the browser that this file will never change and that it will never need to refetch it from the server. This could be a problem for normal files but this is perfect for this usecase because we have control of the clients cache from the server.

Normally these hashes would be added at build/bundle time. But Golang doesn’t have these options so I did it at start-up of the server. Luckily Golang is very fast so it didn’t add any time to the start up (1-2 ms). The implementation works better then expected.

The perfectionist within me did try it with code-gen and it did work, see commit. But it didn’t feel clean or maintainable and was drifting from the goal of simplicity of this project, so I decided to scrap it.

#1713557458


[ mb_dev ]

We do a little refactoring.

Showing 58 changed files with 406 additions and 352 deletions.

Project structure is now much better, less global var’s etc.

#1712417261


[ mb_dev ]

Just added metadata and updated the colour scheme for better contrast. With these two updates completed, I finally have a perfect Lighthouse score.

screenshot of perfect lighthouse score

#1711884999


[ mb_dev ]

Today is the first day of summer time and mb handled it correctly. I did not expect it to work correctly because I can’t recall implementing it.

I think the system will break if you change the time zone after the fact. Posts don’t store time zone data, only a Unix timestamp. Just don’t change the time zone I guess.

#1711279188


[ webdev | mb_dev ]

Finally added the RSS feed to mb. Wasn’t to difficult using the encoding/xml module of the standard lib and exactly 100 lines of code. It’s basic but it’s valid and it works. Maybe I will flesh it out if people actually use it.

[Valid RSS]

#1710620087


[ mb_dev | photography ]

Mb has finally support for file uploads, only images for now. Video and audio is planned, soon™. The blog is more self sufficient with this feature added, not dependent on any other services.

blue bug

photo credit: ii*

#1710601100


[ webdev | mb_dev ]

Just found out a way to add hotkeys to a website without using JavaScript.

<a href="/auth" accesskey="a" aria-hidden="true" tabindex="-1"></a>
<a href="/media" accesskey="m" aria-hidden="true" tabindex="-1"></a>
<a href="/backup" accesskey="b" aria-hidden="true" tabindex="-1"></a>

aria-hidden="true" and tabindex="-1" are there to keep screen readers happy (and to keep my Google Lighthouse score high).

These hidden elements add alt + x hotkeys. It always surprises me how many things the HTML5 spec has integrated.

Shoutout to this article for the idea.

#1709333288


[ golang | docker | mb_dev ]

Docker vs Native binary

Tested the backend of this blog on small VM on my desktop with both a native binary and Docker to compare performance. My desktop could have a lot of variance so this test is not that accurate. The VM has 2GB of ram and 4 cores allocated. Memory is not limiting factor as the webserver uses 20MB at most. All 4 cores are utilised but the one core is always more used then the other, I assume that this is the case because the webserver is database limited for the most part. SQLite is in some ways single threaded.

  1  [|||||||||||||||||||||||||||||||   78.5%] 
  2  [||||||||||||||||||||||||||||||||  80.2%] 
  3  [||||||||||||||||||||||||||||||||  80.3%]
  4  [||||||||||||||||||||||||||||||||||95.7%]

I used the latest version at the time of writing.

I did 3 runs of each, alternating between the two version to limit variation. I used a tool called bombardier with 20 concurrent connections for every 10 second run. The requests are made from the host machine to give the webserver the whole VM to itself. This does add extra overhead but it is the same for both versions, so for sake of comparison this is fine.

These are the averaged results for both versions.

Binary

Statistics        Avg      Stdev        Max
  Reqs/sec       262.03     152.02     913.95
  Latency       75.22ms    53.44ms      0.93s
  Latency Distribution
     50%    71.05ms
     75%   104.18ms
     90%   127.14ms
     95%   143.13ms
     99%   188.12ms
  HTTP codes:
    1xx - 0, 2xx - 2643, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:     3.15MB/s

Docker

Statistics        Avg      Stdev        Max
  Reqs/sec       260.70     150.30     962.85
  Latency       76.59ms    53.97ms      0.95s
  Latency Distribution
     50%    70.67ms
     75%   107.55ms
     90%   135.69ms
     95%   151.88ms
     99%   197.22ms
  HTTP codes:
    1xx - 0, 2xx - 2622, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:     3.12MB/s

These results are really close with a very slight edge for the binary. Only 0.5% more requests per second and 1.78% lower latency on average. This is within the margin of error for this unstable setup. But even if we would take these results as 100% accurate I still think it is worth the small hit in performance. This small hit is probably even smaller when you are using a bigger server on more native hardware.

#1707084791


[ mb_dev | music ]

Custom embeds :D

With this feature done, mb is now ready for its first deployment.

Players never doubt

YouTube Thumbnail
Cover Art