Skip to content

Commit

Permalink
Merge pull request #16 from bots-garden/slingshot-go-pdk
Browse files Browse the repository at this point in the history
✨ Introduce new features: initialize the go-pdk
  • Loading branch information
k33g authored Sep 9, 2023
2 parents f3a1354 + d4bb9c2 commit 32cee7b
Show file tree
Hide file tree
Showing 100 changed files with 2,444 additions and 85 deletions.
5 changes: 4 additions & 1 deletion Taskfile.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
version: '3'

description: >
some helpers
some helpers:
mkdocks:
task mkdocs:serve
env:
MESSAGE: "hello world"
Expand Down
273 changes: 273 additions & 0 deletions docs/slingshot-pdk/go-pdk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
# Slingshot PDK
> Plug-in development kit
## Slingshot Go PDK

### Structure of a plugin

```golang
package main

import (
slingshot "github.com/bots-garden/slingshot/go-pdk"
)

func helloHandler(argHandler []byte) []byte {
input := string(argHandler)
slingshot.Print("👋 hello world 🌍 " + string(input))

return []byte("👋 Hello World 🌍")
}

//export callHandler
func callHandler() {
slingshot.ExecHandler(helloHandler)
}

func main() {}
```

1. You must export a function (it will be called at the execution, here, it's `callHandler`).
2. `slingshot.ExecHandler` is an helper to execute the function (`helloHandler`). This helper will read the wasm shared memory to get the argument of the function (`argHandler []byte`).
3. Then the helper executes the function.
4. And finally write to the wasm shared memory to return the result of the function (`[]byte("👋 Hello World 🌍")`).

#### Build the Slingshot plugin

```bash
tinygo build -scheduler=none --no-debug \
-o print.wasm \
-target wasi main.go
```

#### Run the Slingshot plugin

```bash
./slingshot run --wasm=./print.wasm \
--handler=callHandler \
--input="🤓 I'm a geek"
```

### Slingshot host functions
> 🚧 This is a work in progress
- `slingshot.Print(text string)`
- `slingshot.Log(text string)`
- `slingshot.MemorySet(key string, value string) (string, error)`
- `slingshot.MemoryGet(key string) (string, error)`
- `slingshot.InitRedisClient(redisClientId string, redisUri string) (string, error)`
- `slingshot.RedisSet(redisClientId string, key string, value string) (string, error)`
- `slingshot.RedisGet(redisClientId string, key string) (string, error)`
- `slingshot.RedisDel(redisClientId string, key string) (string, error)`
- `slingshot.RedisFilter(redisClientId string, key string) (string, error)`
- `slingshot.RedisPublish(redisClientId string, channel string, payload string) (string, error)`
- `slingshot.InitNatsConnection(natsConnectionId string, natsUrl string) (string, error)`
- `slingshot.NatsPublish(natsConnectionId string, subject string, data string) (string, error)`

## Other examples

### HTTP nano-service plug-in

```golang
package main

import (
"strings"
slingshot "github.com/bots-garden/slingshot/go-pdk"
"github.com/valyala/fastjson"
)

var parser = fastjson.Parser{}

func helloHandler(http_request_data []byte) []byte {

var text string
var code string

JSONData, err := parser.ParseBytes(http_request_data)
if err != nil {
text = "😡 Error: " + err.Error()
code = "500"
} else {
text = "🩵 Hello " + string(JSONData.GetStringBytes("body"))
code = "200"
}

headers := []string{
`"Content-Type": "application/json; charset=utf-8"`,
`"X-Slingshot-version": "0.0.0"`,
}

headersStr := strings.Join(headers, ",")

response := `{"headers":{` + headersStr + `}, "textBody": "` + text + `", "statusCode": ` + code + `}`

return []byte(response)

}

//export callHandler
func callHandler() {
slingshot.ExecHandler(helloHandler)
}

func main() {}
```

#### Run

```bash
./slingshot listen --wasm=./hello.wasm \
--handler=callHandler \
--http-port=7070
```

### Redis subscriber plug-in

```golang
package main

import (
slingshot "github.com/bots-garden/slingshot/go-pdk"
)

func messageHandler(input []byte) []byte {

slingshot.Print("👋 message: " + string(input))
return nil

}

//export callHandler
func callHandler() {
slingshot.ExecHandler(messageHandler)
}

func main() {}
```

#### Run

```bash
./slingshot redis subscribe \
--wasm=./redissub.wasm \
--handler=callHandler \
--uri=${REDIS_URI} \
--client-id=pubsubcli \
--channel=news
```

### Redis publisher plug-in

```golang
package main

import slingshot "github.com/bots-garden/slingshot/go-pdk"

func publishHandler(input []byte) []byte {

redisURI := slingshot.GetEnv("REDIS_URI")
idRedisClient, errInit := slingshot.InitRedisClient("pubsubcli", redisURI)
if errInit != nil {
slingshot.Print("😡 " + errInit.Error())
} else {
slingshot.Print("🙂 " + idRedisClient)
}

slingshot.RedisPublish("pubsubcli", "news", string(input))

return nil
}

//export callHandler
func callHandler() {
slingshot.ExecHandler(publishHandler)
}

func main() {}
```

#### Run

```bash
./slingshot run --wasm=./redispub.wasm \
--handler=callHandler \
--input="I 💜 Wasm ✨"
```

### Nats subscriber plug-in

```golang
package main

import slingshot "github.com/bots-garden/slingshot/go-pdk"

func messageHandler(input []byte) []byte {
slingshot.Print("👋 NATS message: " + string(input))
return nil
}

//export callHandler
func callHandler() {
slingshot.ExecHandler(messageHandler)
}

func main() {}
```

#### Run

```bash
./slingshot nats subscribe \
--wasm=./natssub.wasm \
--handler=callHandler \
--url=nats://0.0.0.0:4222 \
--connection-id=natsconn01 \
--subject=news
```

### Nats publisher plug-in

```golang
package main

import (
slingshot "github.com/bots-garden/slingshot/go-pdk"
)

func publishHandler(input []byte) []byte {

natsURL := slingshot.GetEnv("NATS_URL")
slingshot.Print("💜 NATS_URL: " + natsURL)
idNatsConnection, errInit := slingshot.InitNatsConnection("natsconn01", natsURL)
if errInit != nil {
slingshot.Print("😡 " + errInit.Error())
} else {
slingshot.Print("🙂 " + idNatsConnection)
}

res, err := slingshot.NatsPublish("natsconn01", "news", string(input))

if err != nil {
slingshot.Print("😡 " + err.Error())
} else {
slingshot.Print("🙂 " + res)
}
return nil
}

//export callHandler
func callHandler() {
slingshot.ExecHandler(publishHandler)
}

func main() {}
```

#### Run

```bash
./slingshot run --wasm=./natspub.wasm \
--handler=callHandler \
--input="I 💜 Wasm ✨"
```
2 changes: 1 addition & 1 deletion docs/slingshot-pdk/intro.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Slingshot PDK
> Plug-in development kit
🚧 This is a work in progress
The Slingshot PDK is a layer under the Extism PDK to ease the writting of a wasm plugin and simplify the call of the host functions.
6 changes: 6 additions & 0 deletions docs/slingshot-pdk/rust-pdk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Slingshot PDK
> Plug-in development kit
## Slingshot Rust PDK

> 🚧 This is a work in progress
1 change: 1 addition & 0 deletions examples-pdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Examples with the Slingshot PDK
2 changes: 2 additions & 0 deletions examples-pdk/go/01-print/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.wasm
slingshot
38 changes: 38 additions & 0 deletions examples-pdk/go/01-print/Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
version: '3'

description: >
task slingshot-build
task wasm-build
task wasm-run
tasks:
# task slingshot-build
slingshot-build:
cmds:
- |
target=$(pwd)
cd ../../../slingshot-server
env CGO_ENABLED=0 go build -ldflags="-s -w" -o ${target}/slingshot
# task wasm-build
wasm-build:
cmds:
- |
tinygo build -scheduler=none --no-debug \
-o print.wasm \
-target wasi main.go
ls -lh *.wasm
# task wasm-run
wasm-run:
cmds:
- |
./slingshot run --wasm=./print.wasm --handler=callHandler --input="🤓 I'm a geek"
# task all
all:
cmds:
- task slingshot-build
- task wasm-build
- task wasm-run
11 changes: 11 additions & 0 deletions examples-pdk/go/01-print/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module print-pdk

go 1.20

require github.com/extism/go-pdk v0.0.0-20230816024928-ee09fee7466e // indirect

require github.com/valyala/fastjson v1.6.4 // indirect

require github.com/bots-garden/slingshot/go-pdk v0.0.0

replace github.com/bots-garden/slingshot/go-pdk => ../../../go-pdk
5 changes: 5 additions & 0 deletions examples-pdk/go/01-print/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
github.com/extism/go-pdk v0.0.0-20230816024928-ee09fee7466e h1:y6pBlzMRaYEBriiyzmT8e82927vBpum357VWi7Lg3/U=
github.com/extism/go-pdk v0.0.0-20230816024928-ee09fee7466e/go.mod h1:3qe+ObKvmOVwzmQDC5A7KzTuvfjImOnWsB1MWU6mWA4=
github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4xc=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
28 changes: 28 additions & 0 deletions examples-pdk/go/01-print/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package main

import (
slingshot "github.com/bots-garden/slingshot/go-pdk"
)

func helloHandler(argHandler []byte) []byte {
input := string(argHandler)
slingshot.Print("👋 hello world 🌍 " + string(input))

slingshot.Log("🙂 have a nice day 🏖️")

return []byte("👋 Hello World 🌍")
}

//export callHandler
func callHandler() {
slingshot.Print("👋 callHandler function")
slingshot.ExecHandler(helloHandler)
}

func main() {}
/*
./slingshot run --wasm=./print.wasm \
--handler=callHandler \
--input="🤓 I'm a geek"
*/
2 changes: 2 additions & 0 deletions examples-pdk/go/02-hello-service/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.wasm
slingshot
Loading

0 comments on commit 32cee7b

Please sign in to comment.