Skip to content

I think my template unit-tests are one of the most beautilful think I’ve ever written. An MF2-JSON document is randomly generated, rendered using the appropriate template and then checked for expected properties matching whatever was in the MF2-JSON.

These are some of the best unit-tests I’ve ever attempted to write.

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0

That feeling when you write a unit test using a library and then accidentally discover a bug in that exact library instead of your own code...

The bug in question, if you’re interested.

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0

i really want to add webmention support and display into Kittybox right now so I wouldn’t be bored of not being able to see if someone interacts with me but i cant code for too much or i will blow a fuse in my brain become a dumb kitty for a week

so i will rest and play minecraft like a responsible person

see? im caring for myself!

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0

Next thing I should do since I fixed the bug: webmentions. I really need to handle webmentions, and I think I actually will be able to do so rather easily now that I know my database doesn’t lock up anymore. I just need to attach an MF2 parser.

In general, what I would want to have in a perfect world is:

  • My own IndieAuth implementation
  • My own webmention acceptor (I already have plans but I need some extra software for it to work)
  • My own media endpoint (that autoconverts pictures to webp)
  • My own Microsub server
  • Editing posts in-band when logged in via IndieAuth
  • Make that second widget at the homepage do something interesting

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0

No more bug. I squashed it for real now.

I should consider adding a regression test so it never shows up anymore. But is it worth it if I caused the bug by being stupid?

Maybe tests were in fact made to guard from stupidity.

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0

Ok, looks like the bug I was talking about (constant hangs in production) was not fixed but rather mitigated. Good news: it’s not hanging now! Bad news: it’s still draining resources and making my server heat up, which makes the onboard fan spin, which makes a lot of noise.

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0

it feels good to write again but quill post editor is not good for tecnical posts with a lot of code because it seems to collapse whitespace in pre blocks

i really need my own editor

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0

It was a restless night. I just fixed my personal website's software, Kittybox, so it wouldn't hang after the first few hours of working (I hope my bugfix finally worked! I've been chasing that bug for months). In an attempt to stimulate my bored brain I was reading some articles on the IndieWeb wikiΒ and stumbled upon discussions that my posts on this very website sparked.

Except the links didn't work. Argh, I can't read my own posts, this won't do!

Of course, this was all my fault. But, thanks to past me having a lot of foresight, this should be rather easy to fix. First thing I decided to do was to patch articles containing links to my posts so the links would actually point to something - despite me wiping my website's main feed, all of the articles are still there because I know some people in the IndieWeb community have been linking to me. The second thing I did not do yet, and if I don't write it down, I might forget it all, so here's the post so I don't forget to do it.

Preserving compatibility

When I was designing the first versions of Kittybox (back then it didn't even had the name!) I was very inspired by 00dani.me's proposed approach of storing MF2-JSON directly in the database. First I stored it in flat files. Then, as I realized my file storage is incredibly slow, I migrated to Redis to keep my dataset in memory. Then several rewrites happened, and the Rust rewrite happened. The database's underlying format was still almost the same, so it was rather easy to port it over. Except I might've forgotten an important step.

In Kittybox, one post can contain several links. One of them is a UID - an authoritative link to the post, the one that Kittybox would use as a primary key in an SQL database if it used one. But since I use the filesystem as my database, the authoritative link gets transformed into an authoritative path which refers directly to the file with the MF2-JSON blob. All other links are supposed to be symlinks.

Except apparently when I was importing the posts in the new file storage backend, I somehow forgot to make all of those symlinks. And that's why the posts don't work.

Past Vika's foresight

Storing the posts in MF2-JSON as processed Micropub data was actually a very good idea. Pretty much all versions of Kittybox filled in alternative URLs (which would be u-url in MF2-HTML and .properties.url[] in MF2-JSON) which actually can be used to restore those permalinks!

Eventually permalink checking will need to be built into the software itself as a consistency check. I could probably write it like this:


use futures::stream::StreamExt;
let urls = json["properties"]["url"]
    .as_array()
    .unwrap_or_default()
    .into_iter()
    .filter_map(|s: serde_json::Value| s.as_str().ok())
    .map(|url| url_to_path(&self.root_dir, url);

let mut url_stream = tokio_stream::iter(urls);
url_stream.for_each_concurrent(2, |path| async move {
    if let Err(err) = tokio::fs::symlink_metadata(path).await {
        if err.kind() == std::io::ErrorKind::NotFound {
            let link = url_to_path(&self.root_dir, url);
            let basedir = link.parent();
            if basedir.is_err() {
                warn!("Database consistency check: couldn't calculate parent for {}", link);
                return;
            }
            let basedir = basedir.unwrap();
            let relative = path_relative_from(&canonical_path, basedir).unwrap();
            if let Err(Err) = tokio::fs::symlink(relative, link).await {
                warn!("Database consistency check: failed to restore symlink {} for {}: {:?}", canonical, path);
            }
        }
    }
});

I'm pretty sure this won't compile out of the box because of borrow checking and variables which need to be bound, but you get the idea. It can be performed on every read (for maximum correctness) or there could be scheduled tasks that sweep the database and perform those consistency checks - I think the second one is the better idea, since it allows me to check even posts that were completely forgotten by everyone. But I'll need to learn how to schedule tasks to run at certain intervals in Tokio - I'm sure there's a function for that though.

When will it be complete?

I hope it will be built into the software soon. For now, I will leave this as a to-do of sorts. A reminder to myself and an example for the others - of both my foresight and my mistakes.

And for now, I could potentially build a script that recursively walks my directory tree and restores symlinks via a cron job. It'll probably work just as well too. But I'll do it later. I wanna sleep...and coffeeeee....

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0

good morning indieweb

i have returned somehow from having my site in semipermanent downtime

please don’t be gentle with it i need a little bit of sustained load so i can check a hypothesis

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0

warp is amazing to cover your code with unit tests. Since everything is a filter, your logic can be tested in isolation (and components that are required, such as database connections, can simply be mocked).

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0

Recording for future reference: I need easy access to creating new channels in Kittybox. The update for the top bar has made all of the channels accessible, so I want to separate my feeds to keep some of the in-the-moment things out of the main feed - for that I need to create a channel, and I don’t know of any Micropub clients that are capable of creating feeds the Kittybox way (specifically, posting an h-feed with a name property as a JSON object).

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0
One of the benefits of a filesystem instead of a database is accessibility for external processing and modification. With databases you often have to use special tools to connect to it directly and modify data; this creates an additional level of complexity compared to just using a text editor to edit, say, JSON files, instead of editing JSON blobs from a command line, or, worse, a graphical editor which was not suited for editing long documents.

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0

Inspired by the mess I’ve made through the years and petermolnar.net’s post I have decided to make all of my previous posts unlisted. The permalinks are not broken - I have preserved what I currently have in the database.

So, I guess I might as well introduce myself once again.

Hello. I’m Vika. I’m currently residing in Russia and I’m the developer of Kittybox, an IndieWeb-enabled all-in-one blogging solution. My favorite thing is homemade burgers and one of the most hated things in my life is all the mild inconveniences caused by capitalism crawling into our lives like a Ctulhu horror. They really add up.

Webmention counters:

  • 0
  • πŸ’¬0
  • πŸ”„0
  • πŸ”–0