リンクの自動ヘルスチェッカー作った
作ったサービス
シンプルなサービスです
url 入力して登録しておくと、定期的に(現状 1 日 1 回)バックグラウンドでリクエストしてリンク切れ等を起こして無いかチェックするサービスです
それだけ
ブログ等の静的なサービスのお役に立てるかも?
こんな感じです
リンクはこちら
ちょっと時間があったので、久しぶり作りました
大体 5 日間くらいかかったと思います
キレてるリンクがあった場合は通知します(今のところ通知方法はメールだけですが、ユーザからの要望次第で slack 等でもできるようにするかもです)
最初は某サービスをパロディして linkedout
ってサービス名にしようと考えていたんですが、linkedout
という id の GCP のプロジェクトが既に存在し、linkedout-XXXX.web.app
みたいなダサい名前になってしまうので linkauto
って名前に変えました
システム
簡単なサービスなので、簡単に作れるように工夫しました
サービスの複雑さとシステムの複雑さは比例するという仮説を個人的に持ってます
サービス
大体こんな感じで google 様におんぶに抱っこの構成です
簡単なサービスなので安さと手軽さに重きを置きました
フロントエンド
ホスティングは firebase hosting を使用しました
React(TypeScript)と vite を使いました
フレームワーク的なところで言うと Material UI 、 swr、react-hook-form、 react-router-dom 等を使用しました
あとは基本的な useState、 useCallback、useMemo、 useContext あたりのフック API を使った感じで、特筆すべきことは何も無いですね
エラー監視は Sentry で行なっています
バックエンド (バックグラウンド)
言語は go を選択しました
理由は単に個人的に好きなことと、Cloud Functions の様なユースケースは go が真価を発揮できる場所の一つだと個人的に考えているからです
仕組みとしては
Cloud Scheduler で特定の Pub/Sub のトピックにメッセージを定期的に送信
それをトリガーにして Cloud Functions を動かしています
このやり方は Cloud Functions をバッチ的に実行するやり方の定番みたいです
ちなみに後で知ったことですが nodejs の firebase-functions
パッケージ だと ↓ を書いてデプロイすれば Cloud Scheduler のジョブと Cloud Pub/Sub のトピック が勝手に作成されるらしいです...恐ろしや
exports.scheduledFunction = functions.pubsub
.schedule("every 5 minutes")
.onRun((context) => {
console.log("This will be run every 5 minutes!");
return null;
});
Terraform そんなに手間じゃないし、function を go で実装したいから全然いいんだけどね...
js 嫌いの自分でもこれはちょっと羨ましいかも
工夫
工夫した点は処理が大きくならないようにチェック対象となるユーザーの抽出とユーザーごとのリンクのチェックは完全に分けて実行しています
関数 1
チェックするユーザーをリスト → リンクチェック用の Pub/Sub トピックが用意してあるので、そこに基本的なユーザー情報を送る
関数 2
上記をトリガーにしてユーザーに紐づくリンクをチェックする
こうすることでメモリや実行時間の点でも気にすることが少なくなります
ユーザの数が増えたり、色々複雑なことをやる必要がでてきたらワークフローエンジンとか使ってやる必要が出てくるかもですが、当分はこれで十分です
Firestore
基本的に RDB を触ってきた人間からすると最初は癖があって戸惑いましたが、少し慣れてくるとこれはこれで面白いなーと感じました
最近仕事でもちょっと使う場面があったのでいい勉強になりました
firestore を触りたいけど全然知らない人はこちらの記事がおすすめです
少し古い記事ですが firestore 入門としてはとてもいい記事だと思います
サブコレクションはいいぞ
firestore 使うとバックエンドを用意しなくていいので簡単なサービスを作る上では最高です
ただし rules はガッツリと書きましょう
不満を言うとリージョンが一つしか選べないのがきついです
デプロイ
システムの立ち上げ系は基本的に Terraform で行いました
ボタンを押していくのはきついので基本的には IaC に全部してしまいたいという思いがあるためです
firebase もできる限り Terraform で立ち上げてます
auth 等 firebase はまだ対応されていないリソースもあるのでそこは手動で補いました
hosting は Terraform 公式ドキュメントがあるのに、実行したらそんなリソースないぞって理不尽にも怒られてしまいました...
Cloud Functions のデプロイは Terraform でもできますが、gcloud コマンドで行なっています
理由はそっちの方が楽そうに思えた、それだけです
本番環境へのデプロイは Github Actions に任せています
Hosting は firebase init で選択できる Github Actions のやつを少し改良して使用
Cloud Functions はこの 2 つと gcloud コマンドでデプロイしてます
何だったんだろ?あれは
(gcloud.functions.deploy) User [***] does not have permission to access projects instance [<project>:getIamPolicy] (or it may not exist): The caller does not have permission.
まとめ
セットアップが簡単、料金が安い等 firebase が個人開発で愛される理由がわかった気がします
今後はページを丸々スクレイピングしてそのページ中のリンクや画像のヘルスチェックを行う機能も開発済みですが、様々な外部サービスとの兼ね合いでどういう形でリリースしようかなと考えています
仮にユーザが増えたとしても広告は入れるつもりはないです
汚くなるのが嫌なので (背に腹は変えられんってなって入れるかもしれませんが、基本的には嫌です)
もしマネタイズするなら上限解放のための課金プランでやろうと考えています
需要があれば使ってくださると嬉しいです
Discussion