Masalah dan senario yang berkenaan
Reka bentuk platform pemberitahuan dikongsi yang digunakan oleh perkhidmatan pengesahan, pesanan, sosial, dan pemasaran. Ia menyokong push mudah alih, SMS, e-mel, dan mesej dalam aplikasi. Mesej transaksi merangkumi OTP dan keputusan pembayaran; mesej pukal merangkumi peringatan acara dan capaian pemasaran. Pemanggil boleh menghantar serta-merta atau menjadualkan pemberitahuan. Pengguna boleh menarik diri (opt out) mengikut saluran dan jenis pemberitahuan, dan mesej pemasaran mesti menghormati waktu senyap dalam zon masa setiap pengguna.
Gunakan andaian temu duga ini:
- Sistem mencipta satu bilion tugas penghantaran saluran setiap hari. Satu pemberitahuan perniagaan yang dihantar melalui kedua-dua SMS dan e-mel dikira sebagai dua tugas.
- Daya pemprosesan purata ialah
1,000,000,000 / 86,400 ≈ 11,600tugas sesaat. Anggarkan kemuncak kempen pada 20 kali ganda purata, atau kira-kira 232,000 tugas sesaat. - Sasaran ketersediaan untuk penerimaan API yang tahan lama (durable) ialah 99.99%, dengan kependaman penerimaan p99 di bawah 200 milisaat.
- Untuk OTP, masa p99 dari penerimaan hingga penyerahan kepada penyedia saluran adalah di bawah dua saat. Kerja pemasaran boleh diratakan sepanjang 15 minit. Kedua-dua sasaran tidak menjanjikan bila peranti benar-benar memaparkan mesej tersebut.
- Jika sampul tahan lama untuk satu tugas penghantaran purata 1 KB, penulisan logik adalah kira-kira 1 TB setiap hari dan 30 TB sepanjang 30 hari, sebelum indeks, replika, resit, dan pemampatan.
Nilai-nilai ini memacu keputusan pemetakan (partitioning), backlog, dan pengasingan; ia bukan dakwaan prestasi penyedia. Pengarangan templat, algoritma pemilihan khalayak, pengebilan, dan ujian A/B adalah di luar skop. Soalan ini menyasarkan peranan backend kanan, platform, dan reka bentuk sistem. Cabaran terasnya ialah mengekalkan keutamaan, kebolehpulihan, dan kebolehcerapan yang jujur merentasi saluran luaran dengan semantik yang berbeza.
Perkara yang dinilai oleh penemu duga
Isyarat pertama ialah sama ada calon mentakrifkan "berjaya dihantar". API 202 bermaksud platform telah menerima kerja secara tahan lama. Respons penyedia yang berjaya biasanya bermaksud penyedia telah menerima permintaan. Penerimaan peranti, paparan sistem pengendalian, dan pembukaan oleh pengguna adalah keadaan terkemudian. Metrik Sends Firebase boleh bermakna mesej telah diaturkan ke dalam baris gilir (queued) atau dihantar ke APNs, manakala respons APNs yang berjaya menerangkan permintaan tersebut. Menggabungkan semua ini ke dalam delivered merosakkan kedua-dua metrik operasi dan tindak balas insiden.
Isyarat kedua ialah sama ada keutamaan disokong oleh pengasingan sumber. Baris gilir yang dikongsi dengan medan keutamaan masih boleh mengalami disk, sambungan pengguna (consumer), dan kuota penyedianya dipenuhi oleh kempen 50 juta pengguna. Reka bentuk yang kukuh memisahkan baris gilir transaksi dan pukal, pengguna, dan belanjawan saluran yang dilindungi sambil membenarkan trafik pukal meminjam kapasiti terbiar. Trafik OTP juga memerlukan had silingnya sendiri; label "kritikal" tidak boleh memintas setiap perlindungan.
Isyarat ketiga ialah bahasa jaminan penghantaran yang tepat. Baris gilir standard boleh menghantar tugas lebih daripada sekali, jadi pekerja harus memproses delivery_id yang stabil secara idempoten. Jika tamat masa rangkaian berlaku selepas penyedia menerima permintaan, penyahduplikasian dalaman tidak boleh membatalkan kesan sampingan luaran tersebut. Tanpa API penghantaran idempoten di pihak penyedia, platform boleh mengurangkan kebarangkalian pendua, merekodkan hasil yang tidak pasti, dan memilih percubaan semula atau failover berdasarkan risiko mesej. Ia tidak boleh menjanjikan penghantaran tepat sekali (exactly-once) dari hujung ke hujung.
Isyarat keempat ialah gelung kegagalan tertutup. Kegagalan kekal menghentikan percubaan semula dan menyahaktifkan titik akhir yang tidak sah apabila berasas. Respons HTTP 429, 5xx, dan kegagalan rangkaian menggunakan backoff berjeda (jittered backoff). Tugas yang tamat tempoh ditamatkan. Ulang main surat mati (dead-letter replay) mengekalkan delivery_id asal dan menyemak semula tempoh luput serta status tarik diri. Resit boleh diduplikasi dan tiba di luar aturan, jadi sistem menyimpan peristiwa mentah sebelum memperoleh keadaan semasa melalui peralihan khusus saluran.
Soalan untuk dijelaskan sebelum menjawab
- Apakah maksud "dihantar" (delivered) kepada perniagaan? Sasaran OTP yang boleh dikawal harus berakhir pada penerimaan penyedia kerana peranti luar talian, syarikat telekomunikasi, dan kebenaran pengguna berada di luar platform. Jika perniagaan memerlukan "dibaca", ia memerlukan resit saluran atau peristiwa klien yang disokong, dengan liputan dinyatakan.
- Siapa yang menetapkan jenis pemberitahuan dan keutamaan? Pelayan memiliki katalog jenis terkawal yang memetakan jenis kepada keutamaan, saluran yang dibenarkan, templat, dan peraturan penarikan diri. Membenarkan pemanggil menghantar
critical=truemembolehkan setiap pasukan bersaing untuk laluan kecemasan. - Mesej manakah yang boleh memintas waktu senyap atau penarikan diri? Hanya jenis transaksi yang diluluskan untuk pengecualian tersebut boleh berbuat demikian. Keutamaan pemasaran disemak sejurus sebelum penggiliran saluran, jadi pengguna yang menarik diri selepas penjadualan akan dikecualikan.
- Adakah fallback silang saluran dibenarkan? Menggantikan SMS yang gagal dengan push mengubah kos, kebolehcapaian, dan jangkaan pengguna. Konfigurasikan graf fallback mengikut jenis pemberitahuan dan bezakan penolakan eksplisit daripada hasil yang tidak diketahui; failover selepas hasil yang tidak diketahui boleh menghubungi pengguna dua kali.
- Apakah susunan (ordering) yang diperlukan? Mesej tetapan semula kata laluan untuk seorang pengguna mungkin memerlukan susunan, manakala amaran sosial biasa biasanya tidak memerlukan susunan global. Kekalkan susunan hanya pada kunci seperti
(user_id, notification_type)untuk mengelakkan pensirian (serializing) keseluruhan sistem. - Apakah batasan pengekalan dan privasi? Kandungan mesej mungkin sensitif. Simpan versi templat dan parameter minimum dalam baris gilir, enkrip medan terpilih, gunakan had pengekalan, dan jangan sekali-kali log OTP, nombor telefon penuh, atau kandungan e-mel.
Rangka kerja jawapan 30 saat
"Saya akan memisahkan penerimaan tahan lama, penerimaan penyedia, penghantaran peranti, dan pembacaan pengguna kepada keadaan yang berbeza. Ingress menulis pemberitahuan dan outbox secara atomik, kemudian mengembalikan 202. Fan-out penerima adalah tidak segerak (asynchronous), dan dasar disemak berhampiran masa penghantaran untuk keutamaan, waktu senyap, tempoh luput, dan penyahduplikasian. Setiap saluran mempunyai baris gilir dan pengguna transaksi, normal, dan pukal yang berasingan, dengan kapasiti penyedia dilindungi untuk trafik transaksi dan kapasiti terbiar dipinjamkan kepada kerja pukal. Pekerja memproses tugas sekurang-kurangnya sekali (at-least-once) di bawah delivery_id yang stabil, mengklasifikasikan kegagalan kekal, had kadar, dan sementara, serta menggunakan backoff eksponen berjeda untuk kes sementara. Panggilan balik penyedia ditambah sebagai peristiwa dan dilipat melalui mesin keadaan saluran, supaya peristiwa 'dihantar' yang tiba di luar aturan tidak boleh mengundur keadaan 'telah dihantar' (delivered). Saya akan menguji lonjakan pemasaran bersama-sama OTP, tugas pendua, dan panggilan balik yang disusun semula untuk membuktikan SLO dua saat dan pemulihan backlog."
Penerangan mendalam langkah demi langkah
API ingress tidak memanggil penyedia SMS atau push secara segerak. Ia mengesahkan pemanggil, mengesahkan jenis pemberitahuan terkawal, menetapkan versi templat, mengesahkan parameter minimum, dan menulis rekod pemberitahuan serta outbox dalam satu transaksi pangkalan data:
~~~text POST /v1/notifications { request_id, notification_type, recipients | audience_id, template_version, template_params, schedule_at, expire_at }
202 Accepted { notification_id, accepted_at } ~~~
request_id menyahduplikasi percubaan semula pemanggil, notification_id mengenal pasti satu pemberitahuan perniagaan, dan delivery_id mengenal pasti satu penghantaran saluran pengguna. Ia tidak boleh menjadi satu pengecam yang sama kerana satu pemberitahuan boleh bercabang (fan out) kepada banyak pengguna dan saluran. Outbox relay menerbitkan hanya selepas transaksi ingress dilakukan (commit), merapatkan jurang antara komit pangkalan data dan penerbitan mesej. Untuk kempen 50 juta penerima, ingress menyimpan rujukan syot kilat (snapshot) khalayak dan kursor; ia tidak mencipta 50 juta baris di dalam satu permintaan atau transaksi.
Perkhidmatan fan-out membaca syot kilat dalam petak-petak dan mencipta kelompok perancangan kecil. Berhampiran masa penghantaran, perkhidmatan dasar memuatkan peraturan jenis pemberitahuan dan keutamaan pengguna semasa, kemudian menilai penarikan diri, waktu senyap, ketersediaan saluran, dasar kekerapan, tempoh luput, dan susunan fallback. Waktu senyap menggunakan zon masa IANA pengguna dan mengendalikan peralihan waktu jimat siang (daylight saving). Jika tiada zon diketahui, produk menggunakan lalai eksplisit dan bukannya menggunakan masa pelayan secara senyap. Tugas yang ditapis menerima SUPPRESSED berserta sebab yang boleh dibaca oleh mesin supaya sokongan boleh menjelaskan sebab ia tidak dihantar.
Data teras boleh dipecahkan kepada tiga rekod:
~~~text Notification( notificationid, tenantid, notification_type, templateversion, scheduleat, expire_at )
Delivery( deliveryid, notificationid, user_id, channel, trafficclass, state, provider, providermessage_id, attemptcount, nextattemptat, stateversion )
DeliveryEvent( deliveryid, providereventid, eventtype, providertime, receivedat, rawpayloadref ) ~~~
Delivery ialah paparan semasa yang dimaterialkan; DeliveryEvent mengekalkan fakta resit penyedia. Kandungan mentah dan data peribadi berada dalam storan terkawal, dengan hanya rujukan dalam jadual peristiwa. Apabila penyedia membekalkan provider_event_id, kuat kuasakan keunikan. Jika tidak, cincang (hash) medan resit yang dinormalkan untuk penyahduplikasian. Sahkan tandatangan webhook sebelum menulis peristiwa dan kekalkan medan yang tidak diketahui secara serasi; medan penyedia baharu tidak boleh merosakkan panggilan balik yang sah.
Sekurang-kurangnya, bezakan keadaan ini:
~~~text ACCEPTED -> PLANNED -> QUEUED -> SENDING -> PROVIDER_ACCEPTED | v DELIVERED -> READ
Terminal side states: SUPPRESSED, EXPIRED, FAILED_PERMANENT ~~~
Rajah tersebut menyatakan peringkat perniagaan, bukan jaminan urutan ketibaan panggilan balik. Penyedia boleh menghantar delivered sebelum sent, dan webhook pendua adalah perkara biasa. Pengendali menambahkan peristiwa idempoten, kemudian mengemas kini unjuran dengan jadual peralihan yang berkuncikan saluran, keadaan semasa, dan peristiwa baharu. sent yang lewat tidak boleh mengundurkan SMS yang sudah berada pada DELIVERED; saluran dengan resit baca boleh mara dari DELIVERED ke READ. Peristiwa yang tidak dipetakan kekal dalam jadual mentah dan mencetuskan amaran dan bukannya memaksa keadaan yang diteka.
Satah data penghantaran memisahkan baris gilir mengikut saluran dan kelas trafik, seperti sms.transactional, sms.bulk, dan push.transactional. Setiap kumpulan mempunyai metrik umur backlog, konkurensi pengguna, dan baris gilir percubaan semula yang bebas. Andaikan kontrak penyedia SMS membenarkan 10,000 permintaan sesaat. Penjadual boleh melindungi 3,000 sesaat untuk trafik transaksi, membiarkan trafik pukal meminjam kapasiti yang tidak digunakan, dan menuntutnya semula apabila trafik transaksi meningkat. Ini adalah contoh konfigurasi; nilai sebenar datang daripada kontrak penyedia dan ujian beban. Penjadualan saksama bagi setiap penyewa (per-tenant fair scheduling) menghalang satu kempen daripada menggunakan seluruh belanjawan pukal, manakala penuaan (aging) menghalang kerja normal daripada kebuluran (starving) selama-lamanya.
Baris gilir yang berasingan memerlukan lebih banyak topik, sambungan, dan konfigurasi operasi berbanding baris gilir tunggal dengan medan keutamaan, tetapi ia mengasingkan backlog disk dan sumber pengguna. Pada skala yang lebih kecil dengan satu saluran, baris gilir yang dikongsi berserta penjadualan saksama berwajaran boleh menjadi lebih mudah. Apabila SLO transaksi dan tarikh akhir pukal berbeza mengikut magnitud yang besar, pengasingan fizikal lebih mudah dibuktikan. Dalam mana-mana reka bentuk, satu penjadual saluran menguatkuasakan kuota sebenar penyedia. Pengguna individu tidak boleh menganggap bahawa mereka masing-masing memiliki kuota penuh.
Pekerja saluran menerima tugas sekurang-kurangnya sekali dan menuntut percubaan secara atomik di bawah delivery_id. Jika penghantaran sudah berada pada keadaan terminal, ia mengesahkan (acknowledge) tugas baris gilir tersebut. Jika tidak, ia menyemak expire_at, memaparkan templat, memanggil penyedia, dan menyimpan respons. Tugas baris gilir yang mendua tidak boleh mencipta rekod penghantaran kedua. Tamat masa luaran masih mempunyai tiga kemungkinan hasil: penyedia tidak menerima permintaan, menerimanya tetapi responsnya hilang, atau mempunyai hasil pemprosesan yang tidak diketahui. Gunakan semula kunci keidempotennan penyedia jika ada. Tanpa ciri itu, tandakan percubaan sebagai UNKNOWN dan selaraskan melalui pertanyaan penyedia atau resit. Pemberitahuan kritikal boleh mencuba semula selepas perniagaan menerima risiko pendua secara eksplisit; pemasaran biasanya boleh menunggu penyelarasan atau tempoh luput.
Klasifikasi ralat menentukan tindakan seterusnya:
- Parameter tidak sah, templat tidak sah, dan token peranti yang disahkan tidak sah adalah kekal. Alihkan ke
FAILED_PERMANENTdan nyahaktifkan titik akhir hanya apabila bukti menyokongnya. APNs 410 bermakna token peranti tidak lagi aktif untuk topik tersebut. - HTTP 429, respons 5xx penyedia, dan kegagalan sambungan secara amnya boleh dicuba semula. Gunakan backoff eksponen, jeda penuh (full jitter), jumlah percubaan maksimum, dan tarikh akhir keseluruhan. Percubaan semula masih melalui kawalan kapasiti saluran supaya pemulihan tidak mencipta lonjakan kedua.
- Kegagalan pengesahan atau konfigurasi akaun ialah insiden platform. Jeda saluran penyedia yang terjejas dan beri amaran; mencuba semula setiap mesej hanya akan memburukkan lagi kegagalan.
- OTP atau peringatan lapuk yang mencapai
expire_atmenjadiEXPIRED. Ulang main surat mati tidak boleh melanjutkan tempoh luput asalnya atau menetapkandelivery_idbaharu untuk memintas penyahduplikasian.
Penerimaan penyedia tidak membuktikan penghantaran peranti. APNs mengembalikan status dan apns-id untuk setiap POST; kejayaan membuktikan kejayaan pada peringkat permintaan. Firebase juga mengira penggiliran atau penyerahan ke APNs sebagai Sends. Penyedia SMS mungkin menawarkan keadaan queued, sent, delivered, undelivered, dan read yang terkemudian, dan webhook-nya boleh berada di luar aturan. Oleh itu, API awam mengembalikan keadaan berlapis berserta status_reason. Laporan mengira kadar penerimaan, penerimaan penyedia, penghantaran yang boleh dicerap, dan pembukaan yang boleh dicerap secara berasingan. Jika saluran tidak mendedahkan sesuatu keadaan, laporkan tidak diketahui (unknown) dan bukannya mengiranya sebagai kejayaan atau kegagalan.
Untuk skala, petakkan jadual pemberitahuan dan penghantaran mengikut notification_id atau masa, dan skalakan baris gilir kerja mengikut saluran, kelas, dan kunci pemetakan. Kerja yang memerlukan susunan bagi setiap pengguna menggunakan kunci pemetakan pengguna yang stabil; tugas pukal yang tidak tersusun boleh dicincang secara lebih sekata. Menyimpan keseluruhan sampul logik 30 TB selama 30 hari dalam indeks dalam talian yang mahal adalah tidak perlu. Simpan keadaan penghantaran terkini dalam talian, mampatkan dan arkibkan peristiwa yang lebih lama, dan kekalkan hanya indeks yang diperlukan untuk pematuhan dan sokongan. Perancangan kapasiti secara berasingan menambah replika, indeks, amplifikasi resit, dan penulisan percubaan semula.
Ujian penerimaan yang menentukan ialah "lonjakan pukal tidak boleh melambatkan OTP." Kekalkan kira-kira 232,000 tugas kempen sesaat, kemudian tambah trafik transaksi. Sahkan bahawa p99 OTP dari penerimaan hingga penyerahan penyedia kekal di bawah dua saat dan backlog pukal mengalir keluar dalam tetingkap 15 minitnya. Suntik respons 429 dan 5xx dan sahkan backoff tidak menyegerak menjadi gelombang percubaan semula. Hantar tugas baris gilir yang sama lebih daripada sekali dan sahkan bahawa ia menggunakan semula delivery_id asal. Hantar panggilan balik mengikut susunan delivered -> sent -> delivered dan sahkan bahawa keadaan tidak pernah mengundur. Lindungi juga penarikan diri sejurus sebelum penghantaran, peralihan waktu jimat siang, surat mati yang tamat tempoh, dan hasil penyedia yang tidak diketahui. Keputusan laluan kegagalan tersebut menjadikan "kebolehpercayaan" boleh diuji.
Contoh jawapan berkualiti tinggi
"Saya akan mentakrifkan empat hasil yang berasingan: penerimaan platform yang tahan lama, penerimaan penyedia, penghantaran peranti yang boleh dicerap, dan pembacaan pengguna. API hanya menjanjikan yang pertama. Ia menulis pemberitahuan dan outbox, kemudian mengembalikan 202. Fan-out adalah tidak segerak, dan peraturan penarikan diri terkini, waktu senyap, ketersediaan saluran, dan tempoh luput dinilai berhampiran masa penghantaran sebelum menetapkan delivery_id yang stabil.
Satu bilion tugas saluran setiap hari secara purata adalah kira-kira 11,600 sesaat, dengan kemuncak kempen 20 kali ganda kira-kira 232,000 sesaat. OTP mesti sampai kepada penyedia dalam masa dua saat, manakala pemasaran boleh diratakan sepanjang 15 minit. Oleh itu, saya akan memisahkan baris gilir dan pengguna mengikut saluran serta kelas transaksi, normal, dan pukal, melindungi kapasiti penyedia untuk transaksi, dan membiarkan pukal meminjam hanya kapasiti terbiar. Setiap penyewa juga mendapat bahagian yang saksama.
Pekerja menganggap penggunaan sekurang-kurangnya sekali. Kerja baris gilir yang mendua menuntut delivery_id yang sama. Ralat kekal akan dihentikan, manakala kegagalan 429, 5xx, dan rangkaian menggunakan backoff berjeda yang dihadkan oleh tarikh akhir keseluruhan. Tamat masa penyedia mungkin telah menghasilkan kesan sampingan luaran. Saya menggunakan semula kunci keidempotennan penyedia jika ada; jika tidak, saya menandakannya sebagai UNKNOWN dan menyelaraskan dan bukannya mendakwa tepat sekali dari hujung ke hujung.
Resit ialah peristiwa tidak boleh ubah (immutable) yang dilipat melalui jadual peralihan saluran, jadi peristiwa 'dihantar' yang lewat tidak boleh menulis ganti 'telah dihantar'. Ujian pelancaran saya menggabungkan kemuncak pemasaran dengan trafik OTP, kemudian menyuntik kerja pendua, respons 429, tamat masa penyedia, panggilan balik luar aturan, dan penarikan diri pada saat akhir. Metrik utama ialah umur baris gilir bagi setiap kelas, kependaman penyerahan penyedia, kelas kegagalan, kiraan UNKNOWN, dan percubaan pengunduran keadaan."
Kesilapan lazim
- Merekodkan 'dihantar' apabila API mengembalikan 202 → hanya penerimaan tahan lama yang selesai → asingkan ACCEPTED, PROVIDER_ACCEPTED, DELIVERED, dan READ.
- Meletakkan semua kerja dalam satu baris gilir keutamaan → backlog pukal masih berkongsi disk, pengguna, dan kuota penyedia → asingkan sumber mengikut saluran dan kelas trafik, dengan peminjaman terkawal.
- Membiarkan trafik kritikal memintas semua had → trafik OTP yang tidak normal boleh membebankan platform dan penyedia → berikan trafik transaksi had silingnya sendiri, amaran, dan kesaksamaan penyewa.
- Mendakwa pengguna menerima tepat sekali kerana baris gilir adalah sekurang-kurangnya sekali → panggilan penyedia mungkin berjaya sementara responsnya hilang → jadikan kerja dalaman idempoten mengikut
delivery_id, selaraskan hasil luaran yang tidak diketahui, dan nyatakan risiko pendua. - Mencuba semula setiap ralat serta-merta → ralat kekal membazirkan kapasiti dan kegagalan 429/5xx mewujudkan ribut percubaan semula → klasifikasikan kegagalan kekal, sementara, pendikit (throttling), dan konfigurasi platform; lakukan backoff bagi kes sementara dengan jeda.
- Menulis ganti keadaan semasa secara langsung → panggilan balik luar aturan boleh mengubah 'telah dihantar' kembali kepada 'dihantar' → kekalkan peristiwa idempoten terlebih dahulu, kemudian kemas kini unjuran dengan jadual peralihan saluran.
- Membekukan keutamaan pengguna pada masa penjadualan → penarikan diri yang terkemudian masih menerima pemasaran → semak semula keutamaan dan peraturan pematuhan berhampiran penggiliran saluran.
- Menetapkan ID baharu semasa ulang main surat mati → penyahduplikasian dipintas dan pemberitahuan lapuk boleh dihantar → gunakan semula
delivery_idasal dan semak semula penarikan diri serta tempoh luput. - Menggunakan susunan global untuk kemudahan → pengguna yang tidak berkaitan menyekat satu sama lain dan satu petak mengehadkan daya pemprosesan → kekalkan hanya susunan tempatan yang benar-benar diperlukan oleh jenis pemberitahuan pengguna.
Soalan susulan dan respons
Susulan 1: Lima puluh juta pengguna mahukan kempen pada pukul 9:00 pagi waktu tempatan. Apakah yang berubah?
Semasa fan-out, bina baldi masa mengikut zon masa IANA dan tarikh tempatan, kemudian hasilkan kelompok terkawal kadar mendahului tetingkap masa mereka. Tambahkan jeda dalam setiap tetingkap sasaran dan bukannya melepaskan setiap tugas tepat pada jam tersebut. Tentukan tingkah laku produk untuk masa tempatan yang tidak wujud atau berulang semasa pertukaran waktu jimat siang, seperti beralih ke masa sah seterusnya dan menghantar tidak lebih daripada sekali sehari. "9:00 pagi" harus bermaksud tetingkap penyerahan penyedia kerana paparan peranti kekal di luar kawalan platform.
Susulan 2: Penyedia mengembalikan kejayaan tetapi tidak pernah menghantar resit penghantaran. Apakah keadaannya?
Kekalkan PROVIDER_ACCEPTED; jangan naikkan tarafnya kepada DELIVERED. Selepas tetingkap pemerhatian saluran, sistem boleh mendedahkan DELIVERY_UNKNOWN untuk operasi, tetapi 'tidak diketahui' tidak boleh dikira sebagai kegagalan. Jika penyedia menawarkan API pertanyaan atau laporan agregat, selaraskan secara tidak segerak dan nyatakan kelewatan serta liputan data tersebut.
Susulan 3: Bagaimana jika panggilan balik delivered tiba sebelum sent?
Tambahkan kedua-dua peristiwa secara idempoten. Unjuran boleh mara daripada PROVIDER_ACCEPTED atau SENDING kepada DELIVERED; sent yang lewat memperkayakan sejarah audit tanpa menurunkan keadaan. Jika penyedia yang sama kemudiannya mengeluarkan pembatalan atau ralat yang didokumenkan, modelkan peralihan khusus penyedia tersebut secara eksplisit dan bukannya meneka susunan daripada integer global.
Susulan 4: Bolehkah dua penyedia SMS melakukan failover secara automatik?
Failover adalah munasabah selepas penolakan eksplisit, kegagalan sebelum sambungan, atau pemutus litar (circuit breaker) seluruh penyedia. Tamat masa selepas penghantaran mungkin bermakna penyedia utama telah menghantar mesej, jadi failover segera meningkatkan risiko SMS pendua. OTP boleh melakukan failover apabila pemilik kos dan keselamatan menerima risiko tersebut secara eksplisit, manakala pemasaran biasanya menunggu pertanyaan, resit, atau tempoh luput. Konfigurasikan keputusan mengikut jenis pemberitahuan dan bukannya secara global.
Susulan 5: Bagaimanakah anda membuktikan bahawa pengasingan keutamaan berfungsi?
Gunakan ujian beban tertutup yang menggabungkan tiga tekanan: backlog pukal yang berterusan, penyewa yang panas (hot tenant), dan respons 429 penyedia yang berulang. Penerimaan memerlukan p99 penyerahan penyedia OTP di bawah dua saat, tiada kerja pukal pada pengguna transaksi, kadar agregat penyedia dalam konfigurasi, dan pemulihan pukal dalam tarikh akhir 15 minit. Kemudian gagalkan satu petak pengguna transaksi dan sahkan bahawa tika (instance) yang selebihnya mengambil alih kapasiti yang dilindungi. Daya pemprosesan purata sahaja tidak dapat membuktikan pengasingan.