減らせたもの
Infra層の削減
Infra層でSpannerに関してはQueryのみを配置して、lib/spannerc packageに配置した1つの関数にQueryを渡すことで実行可能にした。これによりInfra層にQueryごとの関数を用意することがなくなった。Go 1.18からType Parametersが導入されたことで、コード生成ツールを利用せずにQueryに依存しない汎用的な実装をできるようになった。
OpenCensus+SentryからOpenTelemetry+Error Reportingに移行
GoのSDKのOpen Telemetry対応が進んだため移行を進めた。また活用していない割に高い料金を払っていたSentryをError Reportingに移行した。Error ReportingはGoのpanicと同等のフォーマットの出力しかスタックトレースとして認識しないため、エラーラップpackageを独自で実装して出力の形式をpanicに合わせることで対応した。
構造化ログ出力をslogに移行
独自実装をslogに移行した。Goではslog+OpenTelemetryが一般的になった。
ログ分析をLog Analyticsへ移行
今まではAPIのログをCloud Loggingへの出力、sinkの設定、BigQueryへのインポートが必要だったが、Log Analytics向けのログバケットを作るだけでBig Query以上のログ分析が可能となった。
Cloud Run Jobsへ移行
巨大なバッチ処理はDataflowやCloud Tasksで実施していたがCloud Run Jobsへ移行した。Usecaseレイヤーにバッチ処理を書いてmain関数から実行するだけバッチ処理を実装できるようになった。
ページネーション実装
Go 1.23でIteratorが導入されたことでページネーションの実装を減らすことが可能になった。バッチ処理でIteratorを活用することでUsecaseレイヤーでcursorの更新が不要になった。
HTTP周りの改善
他のレイヤーで行っていた処理をHTTP Transportに寄せた。HTTPログ出力、リトライ、otelなど。Graceful Shutdownに真剣に向き合った。
Goの外部依存package
直接依存しているpackageはSDK以外だと13になった。このうち3つはgqlgen、gqlgenc、gqlparserである。
Goのsort packageからslices packageのSortへ移行
Type Parmatersに対応したslices packageへ移行。複数フィールドを対象にしたソートをcmp.Orで実装可能になった。slices package+cmp.Compare+cmp.Orが今後のスタンダードになりそう。
Goのmath/rand packageからmath/rand/v2 packageへ移行
Spannerのスケールアウト制御
SpannerがAuto Scaleに対応した。
Spannerのバックアップ
Spannerのバックアップをするためには、様々なツールを組み合わせて実現する必要があったがスケジュールドバックアップが提供されたので採用した。
SpannerからBigQueryへのエクスポート
BigQueryへのエクスポートは、Cloud Storageに配置してからBigQueryのインポートが必要だったが、External datasetsによって不要になった。
Dockerfileの削除
コンテナイメージは以前からkoを利用しているためDockerfileは利用していなかったがCIイメージでDockerfileを使っていた。現在はGitHub Actionsのアクションを利用する方針に切り替えた。
directiveの指定忘れのツールを削減
今まではdirectiveの用途ごとにLintツールを作成していたが、新規のdirectiveが増えた際に対応コストが高かった。そこでyamlに設定を書くことでdirectiveの指定忘れを検出できる汎用的ツールを実装して移行した。https://github.com/gqlgo/directive
Androidの外部依存ライブラリ
外部ライブラリは、Barcodeリーダー系で3つ、accompanistのpermission、accompanist由来のplaceholder、Ktor、Coil、Apollo、compose-richtext、Timber、libphonenumber、com.ionspin.kotlin:bignum、Google提供のライブラリに抑えられている。
KMPに対応したKtor 3がリリースされた。Ktor 3に対応したApollo 4.10、Coil 3がリリースされた。okHTTPはKtorのエンジンとしてだけ利用して、okHTTPへの依存は減らしてKtor 3だけに依存した。Ktor 2への依存もない。
KtorのDate型とGraphQLのDate型のマッピングをApolloへPull Requestが取り込まれたことで、社内コードから削除。
Navigationをタイプセーフにするためのライブラリはkiwicom/navigation-compose-typedを使っていたが、公式ライブラリへ移行。新たに公式ライブラリがkiwicom/navigation-compose-typedをベースに作られたため、移行コストを抑えられた。公式と同じ選択ができていた。
KotlinにUUIDが入ったので移行。
Apolloのページネーションの状態管理をJetpack ComposeのStateからApolloのページネーションヘルパーに移行。Apollo Kotlinでは将来的に1行でページネーションを実装可能になる。
Javaへの依存を減らしてKotlinに依存を増やした。
変更したもの
Cloud Tasksの非同期処理の関数ジャンプ
Cloud Tasksを利用しているとAPIを叩くことになるため、コードジャンプが難しい。Cloud Tasksのタスクを追加する際にUsecase関数を指定することで関数ジャンプ可能とした。
冪等なユニークなIDを生成するためのUUIDv5
IDにはUUIDv4を利用することが一般的だが、IDを冪等に生成してUpsertすることで冪等な処理を実装しやすくすることができる。これを実現するために一部のテーブルではUUIDv5を採用した。UUIDv5では指定した文字列に対して一意のIDを生成することができる。複合キーを使うこともできるが、今はそうしていない。なんとなく制約が強すぎる気がしている。