データ同期 (datasync)¶
datasync は、YAMLデータファイルを正(source of truth)として、データベースとの差分確認・反映を行うCLIツールです。Terraformの plan / apply と同じ考え方で動作します。
対象リソース¶
| リソース | YAMLパス | DBテーブル |
|---|---|---|
| 画像 | data/images/*.png |
images |
| 問題 | data/questions/*.yml |
questions, questions_single_choice, questions_single_choice_choices, question_images |
| 問題集 | data/workbooks/*.yml |
workbooks, workbook_questions |
| カテゴリ | data/categories/*.yml |
categories |
使い方¶
差分確認 (plan)¶
cd app && go run ./cmd/datasync -data ../data plan
YAMLとDBの差分をterraform風に表示します。データベースへの変更は行いません。
Images:
(no changes)
Questions:
+ 981 (新しい問題のテキスト...)
~ 42
text: "旧テキスト..." → "新テキスト..."
- 500 (削除される問題のテキスト...)
Workbooks:
(no changes)
Categories:
(no changes)
Plan: 1 to add, 1 to change, 1 to destroy.
+追加(YAMLにあるがDBにない)~変更(YAMLとDBで内容が異なる)-削除(DBにあるがYAMLにない)
差分反映 (apply)¶
cd app && go run ./cmd/datasync -data ../data apply
planと同じ差分を計算し、トランザクション内でDBに反映します。
接続先の切り替え¶
--env フラグで接続先を選択できます。
ローカルDB(デフォルト)¶
go run ./cmd/datasync -data ../data plan
# または明示的に
go run ./cmd/datasync -data ../data -env local plan
localhost:5432 のPostgreSQLに接続します。事前に docker compose up -d postgres でDBを起動してください。
dev環境(Neon)¶
# plan
go run ./cmd/datasync -data ../data -env dev plan
# apply
go run ./cmd/datasync -data ../data -env dev apply
AWS SSM Parameter Store (/rikako/dev/database-url) からNeonの接続URLを取得して接続します。
事前に AWS_PROFILE の設定と aws sso login が必要です(AWS CLI セットアップ 参照)。
DATABASE_URL 直接指定¶
DATABASE_URL="postgres://user:pass@host:5432/db?sslmode=require" \
go run ./cmd/datasync -data ../data plan
DATABASE_URL 環境変数が設定されている場合は --env フラグより優先されます。
データ形式¶
問題 (questions)¶
id: 1
type: single_choice
text: 問題文
choices:
- 選択肢A
- 選択肢B
- 選択肢C
correct: 1
explanation: 解説文
images:
- 42
- 43
id: int(ファイル名と一致:1.yml)correct: 0-indexed の正解選択肢番号images: 画像ID(data/images/{id}.pngと対応)
問題集 (workbooks)¶
id: 1
title: 問題集タイトル
description: 説明文
questions:
- 1 # 問題ID
- 2
- 3
questionsの並び順がそのまま出題順序になります
カテゴリ (categories)¶
id: 1
title: カテゴリ名
description: 説明文
workbooks:
- 1 # 問題集ID
- 2
注意事項¶
- apply はトランザクション内で実行されるため、途中でエラーが発生した場合はロールバックされます
- 明示的IDでINSERTするため、apply後にシーケンス(auto increment)は自動でリセットされます
choicesが空の問題ではcorrectの差分比較はスキップされます
dev環境への接続でハマる点¶
- DBドライバは lib/pq。lib/pq は
channel_bindingパラメータを解釈できないため、接続文字列にchannel_binding=requireを含めると接続に失敗する。?sslmode=requireのみにすること(Neonのコンソールが提示するpsql用URLにはchannel_binding=requireが付いているのでそのまま使わない)。 - dev Neon は pooler ホスト(
ep-...-pooler.<region>.aws.neon.tech)を使う。直接エンドポイントだとpassword authentication failed for user 'rikako_owner'になりやすい。 - 接続URLは SSM
/rikako/dev/database-url(SecureString)から取得し、これは Terraform 管理(Neonconnection_uriから登録)。Neon 側でロールパスワードが変わると SSM がズレて全接続が認証失敗するので、terraform applyで再登録するか、暫定でaws ssm put-parameter --overwriteで更新する(手動更新は次の apply で巻き戻る点に注意)。 DATABASE_URL環境変数を直接渡せば--envより優先される。SSM がズレているときの暫定回避にも使える。
CI(plan-datasync)の既知の不具合¶
.github/workflows/plan-datasync.yml の plan 実行ステップは ./datasync ... plan 2>&1 | tail -n +2 > ... とパイプしているため、datasync が非ゼロ終了してもパイプ末尾の tail の終了コードでステップが成功扱いになる。DB接続失敗(認証エラー)でもCIが緑になり、PRコメントにエラー文だけが載るため気づきにくい。set -o pipefail を入れるか、中間ファイルに落としてから tail する形に直すこと。