A brief interlude into Gleam concurrency

I've been learning Rust for a while now.

The other day I came across this little project called Gleam. It's a functional programming language. It's written in Rust. It compiles to JavaScript and Erlang. It borrows a lot of the good bits from Rust while hiding away a lot of the lower-level stuff. It feels kinda like Rust-lite.

I was intrigued, so I took a quick look into it.

If you're also intrigued I recommend taking the Gleam language tour, or keep reading for a quick speedrun.

Gleam is easy to install via Homebrew or your system package manager.

New projects can be made with gleam new my_project.

Packages can be added with gleam add. Let's add gleam_otp with gleam add gleam_otp, which we'll use to spawn new tasks. It will now be an entry in your gleam.toml file, under [dependencies]

gleam_otp = ">= 0.10.0 and < 1.0.0"

I'm interested in Gleam's concurrency handling, so let's test it out. Add the following code to src/my_project.gleam (an example from the Gleam homepage).

import gleam/int
import gleam/io
import gleam/list
import gleam/otp/task

fn spawn_task(i) {
  task.async(fn() {
    let n = int.to_string(i)
    io.println("Hello from " <> n)
  })
}

pub fn main() {
  // Run loads of threads, no problem
  list.range(0, 200_000)
  |> list.map(spawn_task)
  |> list.each(task.await_forever)
}

Compile and run the code with gleam run.

You should see a whole bunch of hellos from different numbers. They appear, at first glance, to be counting in order from 0 to 200,000 like this.

Hello from 44790
Hello from 44791
Hello from 44792
Hello from 44793
Hello from 44795
Hello from 44794
Hello from 44796
Hello from 44797
Hello from 44798
Hello from 44799

The cool thing is though, that each of these tasks is being run concurrently (if you've got a multi-core processor that is ... I think) ...

... And if you scroll back up, you should see that some of the numbers are actually out of order. This is because sometimes — for whatever electronic reason I won't try to understand right now — one of the tasks makes it through your CPU faster than a previous one, thus overtaking it and printing its number out first.

Pretty cool, huh?

Looking forward to exploring more, and maybe using Gleam for when I don't need to be quite as close to the metal as Rust gets me.

A custom Mastodon favicon while you wait

Admin-uploadable custom favicons are officially coming!

But until then, if you are running your own Mastodon instance, you can still do it. This is the easiest way that I've found to do it.

I'll lay it out here, so it's handy for future me, or someone else.

In /etc/nginx/sites-enabled/mastodon add something like this:

location ^~ "/packs/media/icons/" {
  return 301 https://yourdomain.org/favicon.ico;
}

Change yourdomain.org to whatever domain your Mastodon instance is running on.

Then just replace the favicon.ico file in your /home/mastodon/live/public/ directory with the favicon you want.

Restart the Mastodon services with:

# systemctl restart mastodon-*
# or a shell script:

#!/usr/bin/env bash
systemctl restart mastodon-sidekiq
systemctl reload mastodon-web
systemctl restart mastodon-streaming

Then hard-reload your browser. Requests for any favicons (Mastodon uses a few different ones) should now be redirected to your custom one.

This is good enough for me anyway, for now. Looking forward to having this all handled in the admin page soon anyway.

Bye for now!