5.8 KiB
Duty Roster Migrations
Catatan eksekusi 6 file migrasi duty roster di migrations/.
Konfigurasi Tool Migrasi
Tool migrasi yang dipakai project ini adalah goose (Makefile:5) dengan direktori target:
GOOSE_DIR ?= migrations/goose
Konsekuensi: make migrate-up hanya menjalankan file di migrations/goose/. Semua file .sql di root migrations/ — termasuk 6 file duty roster — tidak otomatis dieksekusi. Mereka berfungsi sebagai script SQL ad-hoc / log historis dan harus dijalankan manual (mysql < file.sql) atau dipindahkan ke migrations/goose/ dengan format -- +goose Up / -- +goose Down.
Urutan Eksekusi (by Timestamp)
Goose mengurutkan file by filename ascending. Untuk dua file dengan timestamp sama (20260502), urutannya alfabetis: duty < purge.
1. 20260408_hems_duty_roster_crews_confirm_at.sql
2. 20260429_rename_duty_roster_tables.sql
3. 20260430_normalize_duty_roster_legacy.sql
4. 20260502_duty_roster_permissions_unification.sql
5. 20260502_purge_legacy_hems_duty_roster_permissions.sql
6. 20260504_duty_roster_drop_unique_base_date.sql
Efek per File
| # | File | Efek di DB |
|---|---|---|
| 1 | 20260408_hems_duty_roster_crews_confirm_at.sql |
ALTER TABLE hems_duty_roster_crews ADD COLUMN confirm_at DATETIME NULL (nama tabel lama). Idempoten via IF NOT EXISTS. |
| 2 | 20260429_rename_duty_roster_tables.sql |
RENAME TABLE hems_duty_rosters → duty_rosters dan hems_duty_roster_crews → duty_roster_crews. Pakai guard cek information_schema.TABLES jadi idempoten. |
| 3 | 20260430_normalize_duty_roster_legacy.sql |
(a) Rename tabel lagi dengan guard sama (no-op kalau #2 sukses). (b) Rename kolom hems_base_id → base_id di duty_rosters. (c) Ensure confirm_at ada di duty_roster_crews baru (dan di tabel lama jika masih ada). (d) Rewire FK roster_crews.roster_id & duty_roster_other_persons.roster_id supaya reference duty_rosters (bukan hems_duty_rosters). |
| 4 | 20260502_duty_roster_permissions_unification.sql |
Insert 4 permission canonical: duty_roster.{create,read,update,delete} (skip via WHERE NOT EXISTS). Grant ke role yang punya legacy hems_duty_roster.* ke canonical baru, anti-duplikasi via LEFT JOIN ... NOT EXISTS. Tidak menghapus legacy. |
| 5 | 20260502_purge_legacy_hems_duty_roster_permissions.sql |
(a) Re-insert canonical (no-op jika #4 sudah jalan). (b) Re-grant (no-op). (c) DELETE FROM role_permissions WHERE permission.key IN (legacy). (d) DELETE FROM permissions WHERE key IN (legacy). |
| 6 | 20260504_duty_roster_drop_unique_base_date.sql |
DROP INDEX idx_roster_base_date (sebelumnya unique). CREATE INDEX idx_roster_base_date ON duty_rosters(base_id, duty_date) non-unique. Konsekuensi aplikasi: schema tidak lagi mencegah multiple roster di pasangan (base_id, duty_date) yang sama — kode handler harus mendukung skenario ini (lihat ensureRosterDates yang sebelumnya dedup-by-date). |
Overlap & Redundansi
- #2 ⊂ #3 — File
0430_normalize_legacysudah include semua rename dari0429dengan guard yang sama. File0429secara fungsional redundant; akan no-op jika dijalankan setelah0430. - #4 ⊂ #5 — File
0502_purge_legacyadalah superset dari0502_unification. Insert + grant identik, lalu tambahDELETE. File0502_unificationredundant.
Idempotensi Re-run
| File | Idempoten? | Catatan |
|---|---|---|
| #1 | Ya | ADD COLUMN IF NOT EXISTS |
| #2 | Ya | Guard via information_schema.TABLES |
| #3 | Ya | Setiap ALTER dibungkus prepared statement dengan kondisi |
| #4 | Ya | WHERE NOT EXISTS untuk insert + LEFT JOIN ... IS NULL untuk grant |
| #5 | Ya | Sama dengan #4, ditambah DELETE (idempoten karena hanya hapus key legacy) |
| #6 | TIDAK | DROP INDEX idx_roster_base_date tanpa guard. Re-run setelah index sudah di-drop + recreate (sebagai non-unique) akan gagal karena nama indexnya sama. Mestinya pakai prepared statement guard yang cek information_schema.STATISTICS. |
Versi Minimal yang Setara
Dengan urutan dijalankan penuh, efek akhirnya cukup dicapai dengan 4 file:
0408_..._confirm_at (kompat untuk env yang masih punya hems_duty_*)
0430_normalize_legacy (rename tabel + kolom + FK + confirm_at — superset dari 0429)
0502_purge_legacy (canonical perm + delete legacy — superset dari 0502_unification)
0504_drop_unique_base_date (butuh tambah guard agar idempoten)
Untuk env yang sudah pasti fresh (tanpa sisa hems_duty_* apa pun), kelima file di atas bisa digabung jadi satu file goose-format dengan branch yang relevan saja. Sebelum melakukan ini, pastikan tidak ada DB target yang masih nyangkut di mid-state — file individual lebih aman selama transisi.
Bug yang Pernah Ditemukan Akibat #6
Setelah idx_roster_base_date jadi non-unique, beberapa baris kode aplikasi yang asumsi unique (base_id, duty_date) jadi salah:
ensureRosterDatesdi handler GET/duty-roster/get-all&/get-all/dtsebelumnya pakaimap[string]Rkeyed by date — multiple roster di tanggal sama di-overwrite, hanya 1 yang muncul. Sudah diperbaiki pakaimap[string][]R(multi-value).
Pastikan setiap kode baru yang query/iterasi roster per (base_id, duty_date) menyadari bahwa kombinasi ini tidak lagi unique.