Form 1: Perbaikan Negara. Form 2: Laporan Pemborosan.
Jantung Dibayar Sesuai Takikan berdetak pada jam. Bukan pada kebutuhan. Bukan pada perubahan. Pada timer.
Dua bentuk, satu penyebab utama: sebuah pekerjaan jadwal menggantikan desain yang benar.
Form 1: Perbaikan Negara
Transisi negara gagal selesai atom. Sebagai gantinya, sebuah pekerjaan latar belakang menjalankan pada keterlambatan & merekoncili. Pengguna melihat negara yang rusak selama jendela pemulihan.
Contoh GitHub (2026-04-08): Sebuah permintaan tarik (pull request) repositori upstreamnya menjadi pribadi. GitHub mencoba transisi negara: tutup PR, update status cabang, bersihkan status gabung. Transisi tidak selesai atom. Status PR menunjukkan 'branch-forced-closed' & 'Merge status cannot be loaded' secara bersamaan. Sebuah pekerjaan latar belakang Sidekiq menjalankan menit kemudian & menyelesaikan pemulihan. Pengamatan melihat negara yang rusak selama durasi jendela.
Jantung Dibayar Sesuai Takikan: pekerjaan Sidekiq menjalankan pada jadwal. Tidak menjalankan karena GitHub mendeteksi negara yang rusak; menjalankan karena timer menyalakan. Pengguna yang melihat PR secara real time melihat PR yang bertentangan dengan dirinya sendiri hingga eksekusi pekerjaan berikutnya.
Form 2: Laporan Pemborosan
Laporan atau agregasi menghitung ulang dari awal pada interval tetap. Tidak ada pengecekan cache. Tidak ada pengaman idempotensi. Tidak ada update incremental. Setiap eksekusi: pemindaian penuh.
Contoh: sebuah pekerjaan cron malam yang menghitung ulang jumlah pembelian total setiap pengguna dengan memindaikan semua pesanan dari awal waktu. Sebuah pekerjaan analitik harian yang menghasilkan ulang dashboard dari log acara mentah. Sebuah email ringkasan mingguan yang mengkueri setiap baris di tabel aktivitas.
Setiap menjalankan, baik data berubah sejak eksekusi terakhir atau tidak. Setiap memindaikan sejarah penuh meskipun hanya 24 jam terakhir yang mengandung data baru. Setiap menggantikan repetisi yang dijadwalkan dengan desain incremental.
Akar yang Dibagi
Jantung Dibayar Sesuai Takikan tidak bisa memberi tahu kebenaran tentang negaranya sendiri. Hanya tahu jam. Form 1: pekerjaan perbaikan negara menjalankan pada T+5 menit tanpa peduli apakah negara rusak pada T+0. Form 2: pekerjaan laporan menjalankan pada 2 AM tanpa peduli apakah data berubah sejak kemarin.
Jam tidak membawa informasi tentang apa yang harus dikerjakan. Acara membawa informasi itu: 'transisi negara baru saja gagal,' 'pesanan baru saja datang.' Jantung Dibayar Sesuai Takikan membuang informasi itu & menggantikannya dengan jadwal.
Drain Kapital
Metered Heart menguras kapital hidup: insinyur on call untuk insiden broken-state. Mengerosi kepercayaan sosial: pengguna melihat data yang tidak konsisten & melaporkan kecacatan yang hilang sendiri. Menggandakan MOAD lain: pekerjaan perbaikan state yang memindai semua catatan untuk mencari state broken sering mengandung MOAD-0001 (scan O(N²)). Pekerjaan laporan yang menghitung ulang dingin mungkin menimbulkan MOAD-0005 (stampede cache). MOAD-0009 menggandakan kecacatan lain.
Akar yang Dibagi
Form 1 & Form 2 tampak berbeda di permukaan: satu memperbaiki state, satu menghitung ulang data. Penyebab akar menghubungkannya.
Terbakar pada Perubahan, Bukan pada Jam
Desain event-driven menyalakan api ketika ada perubahan. Transisi state adalah perubahan itu. Perubahan itu adalah trigger.
Form 1: transisi atom menggantikan pekerjaan perbaikan.
Jika transisi state dapat meninggalkan sistem dalam state broken, kecacatan ada di transisi, bukan di kekurangan pekerjaan perbaikan. Perbaiki transisi untuk menyelesaikan atomik (atau transaksional). Ketika transisi selesai atomik, state broken tidak pernah ada. Pekerjaan perbaikan tidak memiliki apa-apa untuk memperbaiki.
# KECAACATAN: transisi non-atomik meninggalkan state broken
def close_pr_on_repo_private(pr_id):
pr = PR.get(pr_id)
pr.status = 'branch-forced-closed' # langkah 1: state parsial
pr.save() # terlihat oleh pengguna SEKARANG
# ... langkah lain mungkin gagal ...
pr.merge_status = 'not_applicable'
pr.save() # langkah 2: sekarang konsisten
# Pekerja Sidekiq merekoncili jika langkah 2 gagal
# PERBAIKI: transisi atomik; tidak ada status intermediate yang terlihat
def close_pr_on_repo_private(pr_id):
dengan db.transaction():
pr = PR.get(pr_id)
pr.status = 'branch-forced-closed'
pr.merge_status = 'not_applicable'
pr.save() # kedua lapangan komit atomik; tidak pernah setengah-tulis
Form 2: pembaruan bertahap menggantikan pemulihan penuh.
Laporan yang kembali dari awal memicu karena data lama + data baru = hasil baru. Tetapi hasil lama + delta = hasil baru yang sama, dihitung bertahap. Acara: data baru tiba. Pelacak: perbarui agregat hanya untuk data baru.
# KEKELIRUAN: pemulihan penuh pada jadwal
def nightly_totals_job():
untuk user in all_users():
total = sum(o.amount for o in user.orders) # scan semua waktu
user.total_purchases = total
user.save()
# PERBAIKI: pembaruan acara-dorong
def on_order_placed(order):
order.user.total_purchases += order.amount # delta hanya
order.user.save()
Pembaruan bertahap memicu saat pesanan tiba, bukan pada pukul 2 pagi. Ini memperbarui hanya pengguna yang terpengaruh. Ini membaca hanya pesanan baru, bukan semua pesanan dari semua waktu. Pekerja malam hilang.
Mengapa Form 1 Menunjukkan Transisi Rusak
Meterai Form 1 Jantung Terukur menunjukkan bahwa transisi status tidak selesai. Pekerja perbaikan ada karena insinyur melihat status rusak & menambahkan mekanisme pemulihan alih-alih memperbaiki transisi. Pekerja perbaikan: perangkat lembaran atas keputusan arsitektural yang rusak.
MOAD-0009 sebagai Penguat
MOAD-0009 memperkuat MOAD lain. Sebuah pekerja perbaikan status yang memindai semua catatan untuk menemukan status rusak: MOAD-0001 (O (N) atau O (N²) scan per jalankan pekerja). Sebuah pekerja laporan yang kembali segalanya dingin: MOAD-0005 (stampede cache saat pekerja mulai & menghubungi sumber panas naungan). MOAD-0009 tidak hanya merugikan sendiri; itu mengirimkan MOAD lain secara teratur.
Diagnosa & Redesign
Sebuah tim menjalankan job cron malam hari pukul 2 AM. Job tersebut meng scan semua pesanan untuk semua pengguna dan merekomputasi jumlah pembelian total setiap pengguna dari awal. Job tersebut memakan waktu 4 jam. Pada pukul 6 AM, dashboard menampilkan total baru. Antara pukul 2 AM & 6 AM, dashboard menampilkan total kemarin.