-
Notifications
You must be signed in to change notification settings - Fork 69
Open
Description
Go version: 1.24
workers version: v0.30.2
I tried to make discord bot using cloudflare workers. All the commands are working normally, except the one that needed a background task.
I'm using this code below for testing as in the fetch-event example, it works without time sleep or very small time sleep, but it gets error when time sleep is longer.
cloudflare.WaitUntil(func() {
for i := 0; i < 5; i++ {
time.Sleep(10 * time.Millisecond) // error when time.Sleep is added
log.Println(i)
}
})
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(InteractionResponse{
Type: InteractionResponseDeferredChannelMessageWithSource,
Data: &InteractionResponseData{
Flags: MessageFlagsEphemeral,
},
})The error:
⎔ Starting local server...
2025/06/11 22:58:51 0
2025/06/11 22:58:51 1
[wrangler:info] POST /api/interactions 200 OK (402ms)
X [ERROR] Uncaught Error: Go program has already exited
at _resume (file:///D:/Go/blegping-discord-worker-go/build/wasm_exec.js:565:11)
at null.<anonymous> (file:///D:/Go/blegping-discord-worker-go/build/wasm_exec.js:285:14)
X [ERROR] Uncaught (async) Error: Go program has already exited
at globalThis.Go._resume
(file:///D:/Go/blegping-discord-worker-go/.wrangler/tmp/dev-Zd86Z9/worker.js:580:15)
at file:///D:/Go/blegping-discord-worker-go/.wrangler/tmp/dev-Zd86Z9/worker.js:332:22
X [ERROR] Uncaught (async) Error: The Workers runtime canceled this request because it detected that your Worker's code had hung and would never generate a response. Refer to: https://developers.cloudflare.com/workers/observability/errors/I also tried this code, get same error also
cloudflare.WaitUntil(func() {
for i := 0; i < 5; i++ {
time.Sleep(time.Second)
}
fmt.Println("5-second task completed")
})Here's my route handler
//go:build js && wasm
package main
import (
"crypto/ed25519"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"log"
"time"
"net/http"
"github.com/syumai/workers"
"github.com/syumai/workers/cloudflare"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
discordPublicKey := cloudflare.Getenv("DISCORD_PUBLIC_KEY")
if discordPublicKey == "" {
http.Error(w, "DISCORD_PUBLIC_KEY is not set", http.StatusInternalServerError)
return
}
msg := "Hello!"
w.Write([]byte(msg))
})
http.HandleFunc("/api/interactions", func(w http.ResponseWriter, req *http.Request) {
discordPublicKey := cloudflare.Getenv("DISCORD_PUBLIC_KEY")
if discordPublicKey == "" {
http.Error(w, "DISCORD_PUBLIC_KEY is not set", http.StatusInternalServerError)
return
}
// log.Println("publickey Env", discordPublicKey)
publicKey, err := hex.DecodeString(discordPublicKey)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// log.Println("publickey", publicKey)
if verified := VerifyInteraction(req, ed25519.PublicKey(publicKey)); !verified {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// log.Println("Reads body")
body, err := io.ReadAll(req.Body)
if err != nil {
http.Error(w, fmt.Sprintf("read body error: %s", err.Error()), http.StatusInternalServerError)
return
}
// log.Println("Parse body")
interaction := Interaction{}
err = interaction.UnmarshalJSON(body)
if err != nil {
http.Error(w, fmt.Sprintf("parse body as interaction error: %s", err.Error()), http.StatusInternalServerError)
return
}
switch interaction.Type {
case InteractionPing:
log.Println("Ping")
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(InteractionResponse{
Type: InteractionResponsePong,
})
case InteractionApplicationCommand:
commandData := interaction.ApplicationCommandData()
// token := interaction.Token
// log.Println(commandData.Name)
switch commandData.Name {
case "background":
// cloudflare.WaitUntil(func() {
// time.Sleep(3 * time.Second)
// res, err := DeferUpdate(cloudflare.Getenv("DISCORD_APPLICATION_ID"), token, "updated message", nil)
// if err != nil {
// log.Println(err.Error())
// } else {
// log.Println(res)
// }
// })
cloudflare.WaitUntil(func() {
for i := 0; i < 5; i++ {
time.Sleep(10 * time.Millisecond)
log.Println(i)
}
})
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(InteractionResponse{
Type: InteractionResponseDeferredChannelMessageWithSource,
Data: &InteractionResponseData{
Flags: MessageFlagsEphemeral,
},
})
case "serverinfo":
log.Println("serverinfo")
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(InteractionResponse{
Type: InteractionResponseChannelMessageWithSource,
Data: &InteractionResponseData{
Content: "Server Info",
},
})
default:
log.Println("unknown command")
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(InteractionResponse{
Type: InteractionResponseChannelMessageWithSource,
Data: &InteractionResponseData{
Content: fmt.Sprintf("Command %s handler not found", commandData.Name),
},
})
}
}
})
workers.Serve(nil) // use http.DefaultServeMux
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels