Capsule 💊 meets Redis at Aiven 🦀

Photo by SpaceX on Unsplash

Capsule 💊 meets Redis at Aiven 🦀

Capsule is my baby, my favorite side project, a set of Wasm plugin runners that allow you to run Wasm programs or serve them as microservices (for more details, you can read this article: Capsule: the Wasm runners project).

Today, I will explain how to develop Capsule Wasm plugins to interact with a Redis database. And this is an opportunity to use the service offered by https://aiven.io/, which offers databases in SaaS mode. And it's good there is a free plan for the Redis database, which is perfect for my demonstration.

Let's start by creating a Redis database at https://aiven.io/

Create a Redis database at Aiven

The creation principle is very simple (create an account before). Here are a few steps on how to do it:

Start by creating a service:

Select the Redis service:

Select the free plan (it's a demo):

Select a geographic area:

You then get the connection data:

You can secure your connection:

You can now finalize the creation of your connection:

You can quickly get your connection information:

I like the "wizards" to connect to the database, whether with the Redis CLI or with your favorite language. It's very convenient:

Create a first Capsule project

There are currently two Capsule runners:

  • the Capsule CLI to run Wasm plugins in a terminal

  • Capsule HTTP, a "tiny" application server to serve Wasm plugins

Install the Capsule CLI

Let's start with the Capsule CLI. To install it, it's simple (here, I use Linux Arm):

VERSION="v0.4.2" OS="linux" ARCH="arm64"
wget -O capsule https://github.com/bots-garden/capsule/releases/download/${VERSION}/capsule-${VERSION}-${OS}-${ARCH}
chmod +x capsule
sudo mv capsule /usr/local/bin
capsule --version

refs:

Create a Capsule plugin

Type the following commands:

mkdir hello-redis
cd hello-redis
go mod init hello-redis
touch main.go

Then modify the content of main.go as follows:

// Package main
package main

import (
    "errors"

    capsule "github.com/bots-garden/capsule-module-sdk"
)

func main() {
    capsule.Log("🚀 starting ...")
    capsule.SetHandle(func(param []byte) ([]byte, error) {

        // add values to Redis
        capsule.RedisSet("message", []byte("Hello World from Capsule CLI"))
        capsule.RedisSet("x_handle", []byte("@k33g_org"))

        // get values from Redis
        message, errMsg := capsule.RedisGet("message")
        xHandle, errHandle := capsule.RedisGet("x_handle")
        errs := errors.Join(errMsg, errHandle)

        if errs != nil {
            capsule.Print("😡 " + errs.Error())
        }

        capsule.Print("👋 " + string(message) + " by " + string(xHandle))

        // get all keys
        keys, err := capsule.RedisKeys("*")
        if err != nil {
            capsule.Print("🥵 " + err.Error())
        }
        for _, key := range keys {
            capsule.Print("🔑 " + key)
        }

        return []byte("👋 That's all folks"), errs
    })
}

Compile and run the Wasm plugin

To compile, type the following commands:

go mo tidy

tinygo build -o hello-redis.wasm \
-scheduler=none \
--no-debug \
-target wasi ./main.go

To run the hello-redis.wasm plugin, use the connection string obtained when creating the service on https://aiven.io/:

REDIS_URI="rediss://default:password@redis-666-capsule.aivencloud.com:17170" \
capsule --wasm=./hello-redis.wasm

And you will get:

023-08-11 07:31:53.166034251 +0200 CEST m=+0.016196746 : 🚀 starting ...
👋 Hello World from Capsule CLI by @k33g_org
🔑 x_handle
🔑 message
👋 That's all folks

Verification

Let's check with the Redis CLI that the data has been created:

redis-cli -u 'rediss://default:password@redis-666-capsule.aivencloud.com:17170'
redis-666-capsule.aivencloud.com:17170> GET message
"Hello World from Capsule CLI"
redis-666-capsule.aivencloud.com:17170> GET x_handle
"@k33g_org"

You see, it's pretty simple 🙂. Now we will create a "nano" service with Capsule HTTP.

Create a second Capsule project: a "nano" HTTP service

Install the Capsule HTTP application server

To install it, once again, it's simple:

VERSION="v0.4.2" OS="linux" ARCH="arm64"
wget -O capsule-http https://github.com/bots-garden/capsule/releases/download/${VERSION}/capsule-http-${VERSION}-${OS}-${ARCH}
chmod +x capsule-http
sudo mv capsule-http /usr/local/bin
capsule-http --version

refs:

  • 📝 doc [Capsule HTTP]

Capsule HTTP is a relatively small application server: 13.75M

Create a new Capsule plugin

Type the following commands:

mkdir hello-redis-web
cd hello-redis-web
go mod init hello-redis-web
touch main.go

Then modify the content of main.go as follows:

// Package main
package main

import (
    "errors"

    "github.com/bots-garden/capsule-module-sdk"
)

func main() {

    capsule.SetHandleHTTP(func(param capsule.HTTPRequest) (capsule.HTTPResponse, error) {

        // get values from Redis
        message, errMsg := capsule.RedisGet("message")
        xHandle, errHandle := capsule.RedisGet("x_handle")
        errs := errors.Join(errMsg, errHandle)

        if errs != nil {
            capsule.Log("😡 " + errs.Error())
        }

        response := capsule.HTTPResponse{
            JSONBody:   `{"message": "` + string(message) + `", "xHandle": "` + string(xHandle) + `"}`,
            Headers:    `{"Content-Type": "application/json; charset=utf-8"}`,
            StatusCode: 200,
        }

        return response, errs

    })
}

Compile and run the Wasm plugin

To compile, type the following commands:

go mo tidy

tinygo build -o hello-redis-web.wasm \
    -scheduler=none \
    --no-debug \
    -target wasi ./main.go 
ls -lh *.wasm

Note: the Wasm plugin weighs only 108K

To serve via HTTP, the plugin hello-redis-web.wasm you will use the connection string obtained when creating the service on https://aiven.io/:

REDIS_URI="rediss://default:password@redis-666-capsule.aivencloud.com:17170" \
capsule-http --wasm=./hello-redis-web.wasm --httpPort=8080

You will get something like this:

2023/08/11 07:55:56 📦 wasm module loaded: ./hello-redis-web.wasm
2023/08/11 07:55:56 💊 Capsule [HTTP] v0.4.2 ⛱️ [beach umbrella] http server is listening on: 8080 🌍

Now you can query your "nano" service:

curl http://localhost:8080

And you will get this:

{"message":"Hello World from Capsule CLI","xHandle":"@k33g_org"}

That's it for today. If you need to make a light "function" that connects to Redis, it's particularly easy with Capsule and setting up a Redis database at Aiven is as simple as it gets 🥰.