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:
📝 doc Capsule CLI
📦 releases Capsule releases
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 🥰.