Open11

syumai/workers + D1 + sqlc で作る workers

zztkmzztkm

タイトルの構成で、Cloudflare Workers API を作りたい。

あとから見返すようでメモる。

zztkmzztkm

とりあえず syumai/workers の Quick Start の通りにやっていく

❯ wrangler generate my-app syumai/workers/_templates/cloudflare/worker-tinygo
 ⛅️ wrangler 3.0.1
------------------
▲ [WARNING] The `generate` command is no longer supported and will be removed in a future version.


Creating a worker in my-app from syumai/workers/_templates/cloudflare/worker-tinygo
✨ Success!

generate 消さるのか。どうなるんだろう。なんか代替あるのかなと思って調べたけど特に出てこなかった。気が向いたらあとでちゃんと調べる。

make dev したら Error: write EPIPE が発生した。

❯ make dev
wrangler dev
 ⛅️ wrangler 3.0.1
------------------
wrangler dev now uses local mode by default, powered by 🔥 Miniflare and 👷 workerd.
To run an edge preview session for your Worker, use wrangler dev --remote
Running custom build: make build
make[1]: Entering directory '/home/zztkm/dev/github.com/pistachiostudio/hello-api'
go run github.com/syumai/workers/cmd/workers-assets-gen@latest
tinygo build -o ./build/app.wasm -target wasm ./...
make[1]: Leaving directory '/home/zztkm/dev/github.com/pistachiostudio/hello-api'
⎔ Starting local server...
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ [b] open a browser, [d] open Devtools, [l] turn off local mode, [c] clear console, [x] to exit                                                                                           │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:30632
            throw a;
            ^

Error: write EPIPE
    at afterWriteDispatched (node:internal/stream_base_commons:160:15)
    at writeGeneric (node:internal/stream_base_commons:151:3)
    at Socket._writeGeneric (node:net:917:11)
    at Socket._write (node:net:929:8)
    at writeOrBuffer (node:internal/streams/writable:392:12)
    at _write (node:internal/streams/writable:333:10)
    at Writable.write (node:internal/streams/writable:337:10)
    at Runtime.updateConfig (/usr/local/lib/node_modules/wrangler/node_modules/miniflare/dist/src/index.js:5120:26)
    at async #assembleAndUpdateConfig (/usr/local/lib/node_modules/wrangler/node_modules/miniflare/dist/src/index.js:9130:23)
    at async #init (/usr/local/lib/node_modules/wrangler/node_modules/miniflare/dist/src/index.js:8894:5)
Emitted 'error' event on Socket instance at:
    at emitErrorNT (node:internal/streams/destroy:151:8)
    at emitErrorCloseNT (node:internal/streams/destroy:116:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  errno: -32,
  code: 'EPIPE',
  syscall: 'write'
}

Node.js v18.12.1
make: *** [Makefile:3: dev] Error 7

解決方法は issue として残させてもらってるのでそちらを参照
https://github.com/syumai/workers/issues/59

解決策を実施して make dev を実行したら成功した。

http://localhost:8787/hello でアクセスできる。

zztkmzztkm

ちょっと目的ははずれるが、せっかく dev 版で、encoding/json が使えるなら試してみたい。

この記事を参考にする。
https://qiita.com/sago35/items/33e63ca5073f572ad69c

ビルドするのが面倒なので、PR 内で作成されたバイナリを使う方法でいく。

ChatGPT3.5 に GitHub CLI で Actions Artifacts から zip をダウンロードする方法を聞いた。

↓次のやつが回答。

zztkmzztkm

GitHub CLI(gh)を使用して、任意のリポジトリのGitHub ActionsのartifactsからZIPファイルをダウンロードする方法は次の通りです。

  1. 最初に、GitHub CLI(gh)をインストールしてセットアップします。GitHub CLIのインストール手順は公式のドキュメントを参照してください。

  2. ターミナルまたはコマンドプロンプトを開き、次のコマンドを使用してGitHub CLIにログインします。必要な認証情報を入力します。

    gh auth login
    
  3. ダウンロードしたいリポジトリに移動します。例えば、owner/repositoryの形式でリポジトリを指定します。

    gh repo clone owner/repository
    cd repository
    
  4. 次に、ダウンロードしたいGitHub Actionsのartifactを特定します。まず、利用可能なartifactのリストを表示するために次のコマンドを使用します。

    gh run list
    

    リストから、ダウンロードしたいartifactのIDを特定します。

  5. 次に、次のコマンドを使用してartifactをダウンロードします。<artifact-id>の部分には、前の手順で特定したartifactのIDを入力します。

    gh run download <artifact-id>
    

    コマンドを実行すると、ZIPファイルがカレントディレクトリにダウンロードされます。

これで、GitHub CLIを使用して任意のリポジトリのGitHub ActionsのartifactsからZIPファイルをダウンロードすることができます。必要に応じて、ダウンロードしたZIPファイルを展開して利用できます。

zztkmzztkm

自分がほしいやつはWebUIですでに決まっていて以下のURLの末尾がIDになる。

 gh run download 5055378092 --repo tinygo-org/tinygo

結構時間かかったけどDLできた。

DLできたら以下のようにインストールする。

❯ cd linux-amd64-double-zipped/
❯ sudo dpkg -i tinygo_amd64.deb
[sudo] password for zztkm:
(Reading database ... 49896 files and directories currently installed.)
Preparing to unpack tinygo_amd64.deb ...
Unpacking tinygo (0.28.0-dev) over (0.27.0) ...
Setting up tinygo (0.28.0-dev) ...

❯ tinygo version
tinygo version 0.28.0-dev-f366cd5 linux/amd64 (using go version go1.20 and LLVM version 15.0.0)

OK !さっそく encoding/json を試してみる

zztkmzztkm

TinyGo 0.28.0-dev と以下のコードで動いた!

main.go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"

	"github.com/syumai/workers"
)

type HelloRequest struct {
	Name string `json:"name"`
}

type HelloResponse struct {
	Message string `json:"message"`
}

func HelloHandler(w http.ResponseWriter, req *http.Request) {
	if req.Method != http.MethodPost {
		w.WriteHeader(http.StatusBadRequest)
		w.Header().Set("Content-Type", "text/plain")
		w.Write([]byte(fmt.Sprintf("request format is invalid: %s", req.Method)))
		return
	}

	var helloReq HelloRequest
	if err := json.NewDecoder(req.Body).Decode(&helloReq); err != nil {
		w.WriteHeader(http.StatusBadRequest)
		w.Header().Set("Content-Type", "text/plain")
		w.Write([]byte("request format is invalid"))
		return
	}

	w.Header().Set("Content-Type", "application/json")
	msg := fmt.Sprintf("Hello, %s!", helloReq.Name)
	helloRes := HelloResponse{Message: msg}

	if err := json.NewEncoder(w).Encode(helloRes); err != nil {
		fmt.Fprintf(os.Stderr, "failed to encode response: %w\n", err)
	}
}

func main() {
	http.HandleFunc("/hello", HelloHandler)
	workers.Serve(nil) // use http.DefaultServeMux
}

開発サーバーを起動してみる。無事に起動したのでビルドも無事に通ったっぽい。

❯ make dev
wrangler dev
 ⛅️ wrangler 3.0.1
------------------
wrangler dev now uses local mode by default, powered by 🔥 Miniflare and 👷 workerd.
To run an edge preview session for your Worker, use wrangler dev --remote
Running custom build: make build
tinygo build -o ./build/app.wasm -target wasm ./...
⎔ Starting local server...

ローカルのAPIを叩いてみる

❯ curl --request POST 'http://127.0.0.1:8787/hello' --header 'Content-Type: application/json' --data-raw '{
    "name": "zztkm"
}'

{"message":"Hello, zztkm!"}

無事に実行できた!

memo: この時点での app.wasm のサイズは 1.9M

zztkmzztkm

頓挫えもんしてるのでどっかで続きやりたい。。。

ただ、sqlc-gen-ts-d1 が思ったより体験良くてモチベあがんねーな