Pendahuluan
Pada arsitektur backend modern, memastikan schema database sinkron dengan definisi model menjadi bagian penting agar fitur baru dapat berjalan mulus. Go Fiber dan GORM sering dipadukan untuk membangun API yang cepat, tetapi migrasi schema memerlukan pendekatan strategis agar dapat dipercaya di lingkungan produksi. Artikel ini membahas cara memanfaatkan AutoMigrate, interface Migrator, dan proses manual untuk mengecek kolom, indeks, serta foreign key, termasuk alur deployment schema versi dan rollback ketika diperlukan. Kita juga akan melihat contoh integrasi migrasi schema ke CLI Fiber saat release.
Strategi Dasar Migrasi di GORM
GORM menyediakan dua pendekatan utama: auto-migrasi dengan AutoMigrate dan migrasi manual melalui interface Migrator. AutoMigrate cocok untuk cepat menyelaraskan tabel dengan struct Go, sementara Migrator menawarkan kontrol granular, misalnya saat perlu mengganti tipe kolom atau membuat constraint yang tidak otomatis.
AutoMigrate: Kelebihan dan Batasannya
Fungsi AutoMigrate(&User{}, &Product{}) akan membuat tabel yang belum ada dan menambahkan kolom baru. Ini cocok untuk fase development dan tim kecil karena mengurangi boilerplate. Namun, AutoMigrate tidak menghapus kolom, tidak mengubah tipe kolom secara otomatis, dan tidak membuat constraint kompleks seperti enum atau partial index.
Contoh implementasi sederhana:
db.AutoMigrate(&User{}, &Product{})Ini cukup untuk memastikan field-field seperti Name string atau Price float64 terefleksi ke tabel. Tapi jika Anda perlu menambahkan constraint unik atau foreign key, AutoMigrate tidak menjamin pembuatan otomatis kecuali dialog struct benar-benar mencerminkan tag GORM.
Migrator: Kontrol Manual untuk Situasi Produksi
Interface Migrator memberi Anda akses seperti HasColumn, AddColumn, CreateIndex, dan CreateConstraint. Hal ini memungkinkan migrasi fase deploy yang lebih terprediksi.
if !db.Migrator().HasColumn(&Product{}, "category_id") {
db.Migrator().AddColumn(&Product{}, "CategoryID")
}
db.Migrator().CreateConstraint(&Product{}, "fk_products_category")
Dengan pendekatan ini, Anda bisa menambahkan kolom hanya jika belum ada, serta memastikan constraint atau index tidak duplikat.
Pengecekan Kolom & Constraint Saat Migrasi
Permasalahan umum di produksi adalah perubahan schema yang tidak tersinkron, entah karena deployment order tidak konsisten atau karena script migrasi gagal di tengah jalan. Teknik terbaik adalah memeriksa keberadaan kolom dan index sebelum mencoba menambahkannya.
- HasColumn: Gunakan untuk menghindari error ketika kolom sudah ada, terutama saat deploy ulang.
- HasIndex: Pastikan index dibuat sekali. Jika index unik diperlukan, pastikan nama konsisten.
- HasConstraint & CreateConstraint: Cek dan buat foreign key secara manual untuk menghindari duplikasi constraint.
Contoh pemeriksaan dan pembuatan index:
if !db.Migrator().HasIndex(&Order{}, "idx_orders_status") {
db.Migrator().CreateIndex(&Order{}, "Status")
}
Untuk constraint foreign key:
if !db.Migrator().HasConstraint(&Order{}, "fk_orders_user") {
db.Migrator().CreateConstraint(&Order{}, "User")
}
Pastikan struktur tag pada struct Go komprehensif, misal:
type Order struct {
ID uint
UserID uint
User User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:RESTRICT;foreignKey:UserID"`
}
Menetapkan Versi Schema dan Alur Deployment
Setiap perubahan schema harus dicatat sebagai versi; ini membantu rollback dan verifikasi migrasi. Pendekatan yang umum adalah menyimpan tabel schema_migrations berisi version dan applied_at. Setiap release migrasi dijalankan berdasar urutan versi.
Alur general:
- Tambahkan file migrasi Go (misalnya
20241001_add_order_status.go) dengan fungsiUpdanDown. - CLI release membaca tabel
schema_migrationsuntuk menentukan migrasi belum dijalankan. - Menjalankan migrasi satu per satu (dengan
AutoMigrateatauMigratorcustom). - Setelah berhasil, catat versi baru ke tabel.
Contoh struktur file migrasi:
func Up(db *gorm.DB) error {
if !db.Migrator().HasColumn(&Order{}, "status") {
return db.Migrator().AddColumn(&Order{}, "Status")
}
return nil
}
func Down(db *gorm.DB) error {
if db.Migrator().HasColumn(&Order{}, "status") {
return db.Migrator().DropColumn(&Order{}, "Status")
}
return nil
}
Catatan: meskipun ada fungsi Down, melakukan rollback di produksi membutuhkan perhatian khusus karena data mungkin hilang jika Anda drop column.
Rollback Manual dan Perlindungan Data
Rollback sering kali tidak otomatis. Jika terjadi kegagalan setelah migrasi, Anda perlu:
- Menjalankan
Downsecara manual untuk membatalkan perubahan schema. - Mengembalikan data dari backup (misalnya menggunakan logical backup atau point-in-time recovery).
- Memastikan tim QA sudah menguji rollback di environment staging sebelum dipakai di production.
Tips debugging:
- Periksa log GORM (gunakan
db.Debug()) untuk melihat SQL yang dieksekusi. - Bandingkan schema antara staging dan production dengan tool seperti
pg_dump --schema-only. - Gunakan environment variable untuk mengunci migrasi hanya di staging/production sesuai kebutuhan.
Integrasi Migrasi dengan CLI Fiber Saat Release
CLI Fiber adalah cara praktis menjalankan migrasi saat release. Anda dapat membuat perintah baru misalnya fiber migrate yang memanggil fungsi migrasi.
Contoh implementasi di file Fiber CLI:
app.Command("migrate", "jalankan migrasi GORM", func(cmd *fiber.CLI) {
cmd.Action(func(c *fiber.CLI) error {
db := config.NewDB()
if err := migrations.Run(db); err != nil {
return err
}
fmt.Println("Migrasi selesai")
return nil
})
})
Fungsi migrations.Run dapat membaca tabel schema_migrations dan mengeksekusi file migrasi terkait. Pastikan CLI hanya dipanggil saat release pipeline sudah siap, misalnya setelah build dan test lulus.
Dalam pipeline CI/CD, Anda bisa menambahkan step seperti:
- Build artifact Go.
- Deploy ke staging dan jalankan
fiber migrate. - Verifikasi schema lewat integration test dan manual check.
- Deploy ke production, lalu jalankan
fiber migrate.
Jika migrasi gagal setelah menambahkan versi baru, pastikan perintah migrasi dapat dihentikan tanpa mengubah tabel schema_migrations agar rollback dapat dilakukan secara manual.
Kesimpulan
Memilih antara AutoMigrate dan Migrator tergantung pada tingkat kontrol yang diperlukan. AutoMigrate sangat cepat di fase awal, sementara Migrator memberikan keamanan untuk production releases. Jaga alur strict untuk versi schema, gunakan pengecekan kolom/index sebelum modifikasi, dan selalu siapkan rencana rollback. Integrasi migrasi ke CLI Fiber membantu memastikan migrasi dijalankan konsisten selama release. Dengan pendekatan ini, schema dan deployment Fiber bisa berjalan lebih dapat diprediksi dan aman.
Komentar
1 komentar
Masuk ke akun kamu untuk ikut berkomentar.
hampir semua framework dan bahasa pemrograman ternyata gini konsep migration nya