Perancangan pohon supervisi

Perancangan pohon supervisi proyek: struktur proses, strategi restart, dan protokol pesan.

Daftar isi

Topik ini merancang pohon supervisi dan protokol pesan proyek puncak sebelum kode ditulis, memakai sistem obrolan sebagai kasus konkret: siapa mengawasi siapa, siapa memegang state apa, dan pesan apa yang mengalir di antara proses-prosesnya. Hasilnya adalah cetak biru yang bisa langsung diterjemahkan menjadi modul dan spesifikasi supervisor.

Pohon dan peran tiap proses#

Pohon obrolan lingkup pertama berangkat dari satu kaidah: setiap state yang hidup harus punya satu pemilik yang jelas dan satu cara pulih. Koneksi tiap pengguna ditangani satu proses pekerja, karena koneksi yang macet tidak boleh merusak pengguna lain. Daftar pengguna daring hidup di satu gen_server, karena satu sumber kebenaran lebih mudah dijaga daripada disebarkan. Riwayat percakapan hidup di tabel DETS yang dibuka oleh satu proses pemilik tabel, sesuai aturan umur proses pada modul Penyimpanan dan binary. Supervisor akar mengawasi ketiganya secara one_for_one, karena kegagalan satu koneksi tidak meragukan riwayat, sedangkan kegagalan proses pendaftar daring cukup serius untuk diberi intensitas ketat:

supervisor akarpendaftar daringpemilik riwayatsupervisor koneksikoneksi Akoneksi B ...gen_server, permanentgen_server + DETSsimple_one_for_one
Pohon supervisi lingkup pertama sistem obrolan
Koneksi per pengguna ditempatkan di bawah supervisor khusus bertipe simple_one_for_one yang spesifikasinya satu dan diulang sesuai permintaan, sehingga menambah dan membuang koneksi tidak mengubah spesifikasi statis. Kebijakan restart koneksi adalah temporary, karena koneksi yang mati berarti pengguna sudah pergi dan prosesnya tidak perlu dibangkitkan. Pendaftar daring dan pemilik riwayat adalah permanent dengan intensitas ketat, karena keduanya harus hidup agar layanan bermakna.

Protokol pesan sebagai kontrak#

Protokol didefinisikan lebih dulu sebagai tuple bertag beserta typespecnya, dan contoh tiga pesan intinya ditulis sebagai berikut:

erlang Inti protokol pesan dan tipe hasilnya
-type nama() :: atom().
-type teks() :: unicode:chardata().

-type perintah() :: {sambung, nama()}
                  | {kirim, nama(), teks()}
                  | {riwayat, nama()}.

-type balasan() :: ok
                 | {terkirim, nama()}
                 | {riwayat, [teks()]}
                 | {error, alasan()}.

-type alasan() :: belum_sambung | penerima_tak_dikenal.

Kontrak ini menuntut tiga hal sekaligus: bentuk pesan yang dikirim pengguna ke koneksi, bentuk balasan yang dijanjikan koneksi, dan daftar kegagalan yang mungkin. Karena kembaliannya bertipe, dialyzer dapat menandai setiap cabang kode yang menjanjikan hal lain, dan PropEr dapat menguji sifat umumnya, misalnya setiap kirim dari pengguna yang sudah tersambung berakhir terkirim atau error tertulis, tidak pernah diam. Protokol yang menyebut unicode:chardata() sejak awal juga menutup persoalan teks sebelum muncul, sesuai aturan string pada modul Record dan string.

Dari cetak biru ke modul dan uji#

Penerjemahan cetak biru mengikuti urutan yang sama dengan urutan pengerjaan pada topik pemilihan proyek: satu modul untuk protokol bertipe, dua modul supervisor dengan spesifikasi di atas, tiga modul gen_server untuk pendaftar, riwayat, dan koneksi, serta satu modul aplikasi yang menautkan semuanya. Setiap modul lahir bersama ujinya: EUnit untuk fungsi murni seperti penguraian perintah, properti PropEr untuk sifat protokol, dan suite Common Test untuk skenario menyambung dua pengguna, mengirim pesan, memulai ulang VM, lalu membaca riwayatnya. Pemeriksaan terakhir adalah kesesuaian dengan cetak biru: supervisor:which_children/1 di tiap lapisan harus menunjukkan struktur yang sama dengan diagram, dan penyimpangan dari cetak biru berarti keputusan desain berubah tanpa dicatat. Ketika seluruh syarat itu terpenuhi, proyek puncak jalur ini selesai sesuai definisi, dan lingkup berikutnya cukup berdiri di atasnya.

Rencana pemulihan per kegagalan#

Cetak biru pohon belum lengkap tanpa tabel kegagalan yang menyatakan reaksi tiap kegagalan. Lima kegagalan yang paling mungkin pada obrolan lingkup pertama dirangkum sebagai berikut:

KegagalanPemulihan yang diharapkan
Proses koneksi crashtidak dihidupkan ulang, status daring dikurangi
Pendaftar daring crashrestart bersih, pengguna menyambung ulang
Pemilik riwayat crashrestart, DETS dibuka ulang dan isinya utuh
VM dimulai ulangriwayat bertahan di DETS, pohon hidup dari awal
Log kegagalan berulangintensitas naik level, dikaji sebagai bug

Tabel ini sekaligus menjadi daftar uji Common Test yang harus ditulis, karena setiap barisnya adalah skenario yang bisa dieksekusi. Perancangan yang berhenti pada diagram pohon masih setengah jalan. Baris kegagalan inilah yang membuat supervisor, state, dan protokol menyatu menjadi satu sistem yang dipahami bersama.

Ringkasan#

  • Setiap state punya satu pemilik: koneksi per proses, daftar daring di satu gen_server, riwayat di DETS milik satu proses.
  • Koneksi memakai supervisor simple_one_for_one dengan restart temporary, sedangkan pendaftar dan riwayat permanent dengan intensitas ketat.
  • Protokol ditulis lebih dulu sebagai tuple bertag beserta typespec hasil dan daftar alasan kegagalannya.
  • Penerjemahannya berurutan dan diakhiri pemeriksaan kesesuaian pohon dengan which_children di tiap lapisan.

Referensi#