🐥
gostry で PostgreSQL の行履歴を Go から軽量にキャプチャする
この記事は ChatGPT を用いて書かれた
gostryとは
gostry は、database/sql トランザクションをラップして PostgreSQL の行履歴を自動で記録する、軽量なGo ライブラリです。INSERT / UPDATE / DELETE をフックして RETURNING 付きで行イメージを取得し、同一トランザクション内で履歴テーブルへ書き込む仕組みを提供します。
使ってみる
1. Handler をセットアップ
handler := gostry.New(gostry.Config{
HistorySuffix: "_history",
SkipIfNotExists: true,
AutoAttachReturning: true,
})
wrapped := handler.Wrap(db)
-
HistorySuffix... ベーステーブル名につけるサフィックス。デフォルトは_history。 -
AutoAttachReturning...RETURNINGのない DML に対しRETURNING *を自動付与(PostgreSQL 専用)。 -
SkipIfNotExists... 履歴テーブルがまだ存在しない場合の挿入をスキップ。
コンテキストに operator / traceID / reason を載せると、履歴テーブルにそのまま保存されます。
ctx := gostry.WithOperator(context.Background(), "cli-user")
ctx = gostry.WithTraceID(ctx, "trace-demo-001")
ctx = gostry.WithReason(ctx, "demo run")
2. トランザクションを実行
tx, _ := wrapped.BeginTx(ctx, nil)
defer tx.Rollback()
// RETURNING なしでも OK(AutoAttachReturning が有効な場合)
_, _ = tx.ExecContext(ctx, `UPDATE orders SET status='paid' WHERE id=$1`, orderID)
// 監査対象外にしたいクエリは WithSkip で除外
skipCtx := gostry.WithSkip(ctx)
_, _ = tx.ExecContext(skipCtx, `DELETE FROM temp_table`)
_ = tx.CommitContext(ctx)
履歴テーブル構造の初期化は SchemaConfig + Migrate が便利です(既存テーブルの型を introspection して履歴テーブルを作成)。構造体に
TableName() を実装していれば、そこからテーブル名解決も可能です。
cfg := gostry.SchemaConfig{HistorySuffix: "_history", CreateIDIndex: true}
if err := gostry.Migrate(ctx, db, cfg, Order{}, "payments"); err != nil {
log.Fatal(err)
}
監査テーブルの例
CREATE TABLE orders_history
(
history_id BIGSERIAL PRIMARY KEY,
id UUID,
operation TEXT NOT NULL,
operated_at TIMESTAMPTZ NOT NULL,
operated_by TEXT,
trace_id TEXT,
reason TEXT,
before JSONB,
after JSONB
);
期待できる利点
- アプリの SQL をそのまま利用しつつ、履歴の JSON を行単位で蓄積
- トリガーや外部イベントストアを持たなくても監査証跡を確保
-
SkipFuncやWithSkipで運用中のメンテナンス・バッチを柔軟に除外 - Postgres 固有の識別子(スキーマ/引用符)もライブラリ側で安全に扱える
注意点
-
AutoAttachReturningはベストエフォートです(ON CONFLICTや複雑なバッチ構文は書き換えず、そのまま実行します)。 - 行数が多い場合は
history_idのような順序キーでマネジメントしたり、CreateIDIndexを有効にするなどの調整が必要です。 - 履歴テーブルが増えるので、適宜パーティショニングや TTL パージなどのメンテナンスを検討してください。
記事をご覧いただきありがとうございました!フィードバックや Issue 大歓迎です 🙌
Discussion