Open19

近所の耳鼻科のWeb予約をするためのWebサービスを作る(謎)

tenkohtenkoh

スクラップのタイトルの謎さは謎のままにしておく…。

今回は既存のGo CLIをWebサービスに移植していこうと思いまーす。

せっかく移植するのでいろいろ新しいものを触りたい、ということで以下のポイントを盛り込んでいきましょう。

  • お金をかけずに運用したい。Cloudflare (Workers + D1) を使い倒す。
  • 既存のGo CLI資産を使いたい。syumaiさんのWorkersを使ってみる。
tenkohtenkoh

必要な機能は以下の通りです。

  • 予約の追加
  • 予約履歴(待機中 + 過去履歴)
  • 予約の実行

上記機能を実現するための要素は以下の通りです。

  • フロントエンド(新規予約、予約履歴)
  • データベース(予約の管理)
  • Cron job(予約可能時間になったら予約を実行)

おおまかに次のような構成にしようと思います。

frontend (Worker1) <---> D1 <---> cron job (Worker2)

frontendから予約をD1にスタックしていきます。 予約競争がマジで熾烈なので、予約可能時間の少し前(10秒とか)にcron jobを起こし、そのWorker内で予約可能時間を待つようにします。予約が完了したら結果をD1に書き込みます。

tenkohtenkoh

cron jobの方には既存のGo CLIのロジックを移植したいので、github.com/syumai/workersを使ってみたいと思います。

https://github.com/syumai/workers

ずっと使ってみたかったんですよね。

ほんとのほんとに余談ですが、syumaiさんなのかshumaiさんなのかいつも悩む…。(すみません)

tenkohtenkoh

フロントエンドの方はなんでも良いです。迷い中です。同じようにGoで書いた方が個人的には早そうです。ただHonoも使ってみたい。あとで考えましょう。

tenkohtenkoh

まず githug.com/syumai/workers を使って cron job を作る練習をしてみたいと思います。

tenkohtenkoh

github.com/syumai/workers/_example/cron をビルド&デプロイしてみます。

  1. 事前にCloudflareへの登録は済ませておく
  2. リポジトリをクローンして、cd _example/cron
  3. npm i wrangler --save-dev。ちょっとよくわからないんだけどwranglerはグローバルインストールしない方がいいのかな?
  4. npx wrangler deploy

おしまい!

気づき:

  • cronなので外部に公開する必要は無い。wrangler.tomlworkers_dev = falseにすることで非公開 = Routesが0になる。
tenkohtenkoh

実際にデプロイできているか確認してみよう。ダッシュボードからworkerを見てみる。

ログを収集すると確かにできている。サンプルアプリではfmt.Printlnしているが、logレベルでmessageに値が入るらしい。

tenkohtenkoh

cron は現状では wrangler devでローカル挙動確認できなさそう。

tenkohtenkoh

ビルドは通るけど、開発中に import でエラー表示されるの気になる。あ、syscall/jsをインポートしているからGOOS=js GOARCH=wasmにしないとダメですね。

tenkohtenkoh

あんまり気にしないようにするけど、VSCode上でGOOS,GOARCH切り替えるのどうしたら良いんだろう。グローバルに書き換えないとだめ?

tenkohtenkoh

TinyGoでビルドするとnet/httpないよエラーがでる。開発版のせい?面倒だけどあとでdevcontainerとかで確認してみようかな。ひとまずGoでビルドして、他に気になることを色々確認しておく。

tenkohtenkoh

github.com/labstack/echo/v4とか使えると簡単で助かる。workers.Serveに試しにechoを渡してみると普通に動く。神。

tenkohtenkoh

ただ、Form送信 -> 処理中ページ -> 処理結果ページ みたいなことをやろうとして、処理中ページにリダイレクト処理を入れるとコケる。エラーをみるとこんな感じ。根が深そう。リダイレクトを使わなくて良いようにフォームのデフォルト処理は止めて、APIを叩きにいく感じにしようかな。

[wrangler:err] TypeError: Cannot read properties of undefined (reading 'exports')
    at syscall/js.valueNew (file:///(省略)/app/build/wasm_exec.js:395:24)
    at globalThis.Go._resume (file:///(省略)/app/build/wasm_exec.js:553:23)
    at Object.handleRequest (file:///(省略)/app/build/wasm_exec.js:564:8)
    at Object.fetch (file:///(省略)/app/build/shim.mjs:51:18)
    at async jsonError (file:///(省略)wrangler/templates/middleware/middleware-miniflare3-json-error.ts:22:10)
tenkohtenkoh

あ、前提条件として、全ルートに認証をかけてるのもあるかも