GASの便利さと「そうなんだ」ポイント
GASって便利ですよね.
初めて知ったときは,VBAのGoogle版くらいの認識でしたが,Twitterのbotも作れるし,Google AdsenseのAPIと連携すれば収益レポートのメールを送付できますし.
今回はGASをWebAPIサーバとして利用しました.
その話をします.
ただしWebAPIサーバの設定方法をメインではしません.ググればたくさん出てきますし,僕よりも詳しい方がたくさんいらっしゃるので,
そうなんだ〜と思ったところをメモレベルで書きます.
そもそも何やったのか
WebアプリのサーバサイドをまるっとGASにしました.
この記事です.
記事の冒頭にもコメントしてますが,当初のアプリとしてはJuliaのHTTP.jlでWebAPIを実装し,データベースをPostgresにしました.
その構成でいったんAWSにデプロイしてみようと画策していて,Terraformを使うのが作るのも壊すのも楽かな,クライアントサイドはTypeScriptで書いているからCDKTF気になっていたし使ってみようかなとやってみたところ,まぁ大変.
ECS,Terraform,TypeScriptの知識が足りないから全然進まず.
ということもあって,AWSだとお金もかかるし,render使おうと思いました.
renderっていうのはこちらです
コンテナ(Dockerfile1個分まで)なら無償で利用できます.
ただ色々制限はあります.
Dockerfile1個分に加えてマネージドのpostgresのサービス1個を無料枠で共存はできないようでした.どっちか1個じゃなきゃダメらしく.英語を読めてないだけで,実は無料で両方利用可能でしたら,嘘言ってすみません.ChatGP君もできないはずと言っていたのですが.
クライアントサイドのNext.jsのコンテナをrenderにデプロイし,インターネット経由かよと呆れてしまうのですが,無料でやりくりするならAPI機能があったGAS使うしかない!ということでGASをサーバサイドに使いました.
データベースはそんな複雑なことをしないアプリなので,スプレッドシートに代用させてます.
メモ
GASからのAPIリクエスト失敗
本当の原因がわかってないのですが,GASから三菱UFJさんが公開しているAPIにリクエストを飛ばすと失敗しました.
以前,Google Colabから実行したときも失敗した経験があって,その時はcloud frontで拒否されているみたいなエラーメッセージが出てました.
ローカルPCから出来てColabから出来ないことから,地域によるIP制限とかあるのか?と思い,ChatGPTに聞いたところ,その可能性があると回答されました.
Colabで試したときは,Googleのデータセンターが海外だからしゃーないかな〜と諦めたのですが,今回GASで失敗した際に「ワンチャンガチャ回す感覚でやっていけば,東京リージョンからリクエストされるんじゃなかろうか?仕組みはよくわかってないけど」と連発してみたら上手くいくときは上手くいく!
面白いですね,クラウドって.
ColabやGASから外部にリクエストして失敗したときは,たまたまそのリクエストが海外のデータセンターにあるサーバからリクエストされたんじゃないのかと考えてみるのもありかもしれないです.
これは経験則レベルなのですが,予想通りと言えば予想通りなのですが,1個のGASのジョブで複数回リクエストしていると,最初が成功すれば残りは全部成功します.
1回目は成功,2回目は失敗,3回目は成功とかだったらスクリプトの処理書くの面倒だなと思ったので良かったです.
このガチャの性質上,スプレッドシートの更新も失敗するため,GASのトリガーで朝昼晩で3回実行されるようにしています.価格自体はサンプリングが1日単位なので,1回更新すれば十分なため,頻繁にリクエストしすぎずとはいえ程よく更新できればいいなという思いでこの形になりました…
もっさりしちゃう
上の記事からデモ利用できると思うのですが,すごくもっさりしたアプリになってます.
renderがそもそも日本から一番近くてシンガポールリージョンにしかないとのことですが,クライアントサイドの描画よりもGASからのレスポンスが遅いですね.インターネット経由しているからというか,直接GASのエンドポイント叩いても遅いです.
Webアプリの機能をメインに提供されているわけではないので仕方ないと言えば仕方ないのですが…
GASでAPI作成まわり(小ネタ)
エンドポイントを複数用意できないようで,1個のエンドポイントでクエリを使って分岐する方針になりました.ここも移植という観点で言うとHTTP.jlとは変わるので,ちょっと困惑しました.
あと,doGet関数でリクエストを受けた時の処理を記載しなきゃいけないらしく,自分オリジナルの名前の関数で作っていたらdoGetが見つからないとエラーが出ました.
その他,返り値について,以下のようにひと思いに書いてますが,これもsetContentしたりsetMimeTypeをする箇所を分けるとうまくいかなかったからです.
ChatGPTにこうしろと言われて以下のような形になったので,ネット記事に書いてくださっている方のコードをコピペしてなぜうまくいかなかったのか,正確にいうとレスポンスのContentTypeがapplication/jsonではなく,text/plainになってしまったのかはよくわかってないです.
ChatGPTくんがこの時点ですでにテキストができてしまっていて〜みたいな説明をしてくれた気がしたのですが忘れてしまいました.ちゃんと関数の機能を調べたり,切り分けとかすればいいのですが結局やれてないです…
ContentService.createTextOutput(JSON.stringify(output)).setMimeType(ContentService.MimeType.JSON);
まとめ
GASはすごい.
色々つまづいたポイントはありましたし,JavaScript経験が少なくて大変でしたが,GASの時間形式でのスクリプト無料実行によって定期的にスプレッドシートの中身も更新できますし,それによってAPIリクエストガチャの失敗も緩和できてますし最高です
付録
今回話したデモアプリはこちらで.
データは過去3ヶ月分です.
本当はAPIで提供されているファンド全部で,過去1年分くらい表示させたいのですが,その条件でスプレッドシートに書き込んでいるとGASの実行時間制限に引っかかってしまうための結果です.HTTP.jlとPosgtresを使っている際はjuliaのマルチスレッドのマクロ使って書き込み時間の圧縮をしていたので,非同期処理ができればワンチャンあるかもしれないですね…
それはさおてき,なるべくPCから見ることを想定しています.CSS初心者すぎてスマホ対応がいまいちうまく出来ておらず.
Discussion