Apabila anda bertanya kepada mana-mana pengendali TV langsung apa yang mereka mahu lihat dalam alat penjadualan, mereka hampir selalu berkata, "Biarkan saya bina saluran seperti saya mengatur fail dalam folder. Seret program masuk, lepaskannya di mana saya mahu, selesai.
Masalahnya ialah jadual saluran bukanlah folder. Ia adalah dokumen undang-undang dengan kekangan yang ketat. Dua program tidak boleh dimainkan pada masa yang sama. Pengekod tidak boleh menukar input lebih cepat daripada setiap lima saat. Program yang sudah bermula tidak boleh diedit. Dan filem yang berjalan melepasi tengah malam perlu dianggap sebagai satu program, bukan dipotong pada sempadan hari.
Setiap tindakan seret dan lepas adalah pelanggaran kekangan yang berpotensi berlaku. Ini adalah kisah kejuruteraan tentang bagaimana penjadual mStudio menukar seret dan lepas yang mesra pengendali menjadi garis masa saluran yang sah di AWS MediaLive โ termasuk saat pengendali melepaskan program terus di atas program lain โ dan mengapa sistem menyelesaikan konflik tersebut secara automatik daripada memberikan pengendali ralat dan teka-teki untuk diselesaikan.
Gambaran Keseluruhan Pantas
| Aspek | Perincian |
|---|---|
| Domain | Penjadualan seret dan lepas untuk saluran FAST langsung di AWS MediaLive |
| Penyelesaian konflik | Auto-anjakan melalui algoritma snap 4-peraturan |
| Jurang jiran minimum | 6 saat (minimum 5s MediaLive + 1s keselamatan hanyutan jam) |
| Pengendalian kaskad | Masa asal diingati pada sentuhan pertama, jadi anjakan berantai menghasilkan satu panggilan pembersihan bersih setiap program |
| Keselamatan tarikh lalu | Pengawal dua fasa โ penolakan input, ditambah pemulihan senyap selepas snap |
| Keselamatan hari reset | Buffer main balik langsung 2 minit, ditambah pemeliharaan bawa ke hadapan |
| Status | Dalam pengeluaran |
Masalah Perniagaan: Kalendar Yang Bukan Kalendar
Penjadualan saluran kelihatan seperti perisian kalendar. Pengendali mengharapkan ia berfungsi seperti satu โ seret filem ke slot 9 PM, geser program ke atas garis masa, tambah siri secara berkumpulan dan lihat episod disusun satu demi satu. Tetapi jadual saluran langsung membawa kekangan yang kalendar tidak ada:
- Program tidak dibenarkan bertindih. TV langsung memainkan satu perkara pada satu masa.
- Pengekod mempunyai jarak tindakan minimum. AWS MediaLive tidak akan menukar input lebih cepat daripada setiap 5 saat. Jadualkan dua program 4 saat berasingan, dan penyebaran ditolak.
- Program lalu tidak boleh diedit. Masa siaran telah berlalu; bit sudah berada di skrin penonton.
- Program silang tengah malam adalah satu unit. Filem yang berjalan dari 23:30 hingga 01:15 perlu dikendalikan sebagai satu program, bukan dua separuh program yang dibahagi pada sempadan hari.
"Hampir bertindih" dua saat bukanlah kesalahan pengendali โ ia adalah hasil semula jadi daripada menyeret dua program yang hampir, tetapi tidak sepenuhnya, sesuai bersama. Cabaran kejuruteraan sebenar adalah menterjemahkan "seret filem ke 9 PM" menjadi "jadual saluran yang sah." Jika salah, pengendali sama ada menghadapi dinding ralat pada setiap lepas, atau โ lebih buruk lagi โ mendapati pada masa siaran bahawa pengekod secara senyap menolak sebahagian daripada jadual.
Apa yang "Sah" Bererti di AWS MediaLive
Untuk jadual menjadi sah di MediaLive, program bersebelahan mesti sama ada:
- Bersebelahan โ tiada jurang antara mereka, atau
- Dipisahkan sekurang-kurangnya 5 saat โ jarak tindakan minimum pengekod.
Perangkapnya adalah segala-galanya di antara. Jurang 1 saat, jurang 3 saat, jurang 4.9 saat โ semuanya kelihatan baik dalam UI, dan semuanya ditolak pada masa penyebaran. Lebih buruk lagi, penolakan bukanlah kegagalan atom yang bersih; ia boleh mengakibatkan saluran yang sebahagiannya disebarkan, di mana beberapa tindakan jadual mendarat di MediaLive dan yang lain tidak.
Tambah margin keselamatan 1 saat untuk hanyutan jam antara pelayan aplikasi dan AWS, dan lantai praktikal menjadi 6 saat, bukan 5. Nombor tunggal ini โ MIN_NEIGHBOUR_GAP_MS = 6000 โ adalah satu pemalar yang keseluruhan sistem penyelesaian konflik dibina di sekelilingnya.
Mengapa Pendekatan yang Jelas Gagal
Sebelum menetapkan penyelesaian automatik, beberapa strategi yang lebih jelas telah dipertimbangkan dan ditolak:
"Tolak sebarang ketidaksepakatan dan minta pengendali menyelesaikannya." Kerana ini, pengendali mesti melakukan matematik snap secara manual pada setiap lepas. Seretan lima saat menjadi teka-teki lima minit, dan teka-teki menjadi lebih sukar apabila senarai main berkembang. Dalam praktiknya, pengendali meninggalkan seret dan lepas sepenuhnya dan kembali kepada spreadsheet.
"Snap semuanya ke sempadan 5 minit supaya tiada apa yang bertindih." Ini menyelesaikan masalah teknikal dengan memusnahkan niat pengendali. Program yang dimaksudkan untuk bermula pada 21:03:15 tidak sepatutnya melompat secara senyap ke 21:05:00. Jadual itu milik pengendali, bukan fungsi pembundaran.
"Kesan konflik pada masa penyebaran dan bukannya masa lepas." Ini terasa lebih pantas dalam UI, tetapi ia memindahkan kegagalan ke saat yang paling teruk. Apabila pengendali mengklik Deploy dan melihat "jadual ditolak pada program 47," mereka telah bergerak mental dari edit yang menyebabkannya.
"Benarkan jurang mikro dalam UI dan biarkan MediaLive menolaknya." Ini menolak ralat pengekod yang tidak jelas kembali kepada pengendali, dan boleh meninggalkan saluran dalam keadaan separuh disebarkan yang benar-benar sukar untuk dipulihkan.
Tuil yang benar-benar berfungsi adalah menyelesaikan konflik secara automatik, pada masa lepas, menggunakan peraturan deterministik โ dan mencerminkan garis masa yang diperbetulkan kembali kepada pengendali dengan segera.
Penyelesaian: Algoritma Snap Empat-Peraturan
Pada setiap lepas, algoritma snap memeriksa setiap pasangan program bersebelahan pada saluran yang terjejas โ baru-ke-baru, baru-ke-sedia ada, atau pasangan sedia ada-ke-sedia ada yang jurangnya berubah kerana lepas โ dan menggunakan tepat satu daripada empat peraturan berdasarkan jurang antara mereka:
- Jurang = 0 โ tiada tindakan. Bersebelahan adalah sah, dan hampir pasti apa yang dimaksudkan oleh pengendali.
- Jurang โฅ 6 saat โ tiada tindakan. Pengendali sengaja meninggalkan ruang, mungkin untuk slate atau pod iklan.
- 0 < jurang < 6 saat โ anjak program kedua ke belakang untuk menutup jurang kepada sifar.
- Jurang negatif (bertindih) โ anjak program kedua ke hadapan dengan jumlah bertindih.
Pentingnya, algoritma memproses pasangan bersebelahan dalam satu laluan ke hadapan tunggal ke atas garis masa yang disusun. Setiap program yang diubah segera menjadi item "sebelumnya" untuk perbandingan seterusnya โ jadi lepas yang mencetuskan reaksi berantai anjakan diselesaikan dalam satu perjalanan linear, tanpa memerlukan rekursi.
Diagram 1 ยท Pokok Keputusan Snap

Seni Bina Sistem
Penjadual dibina di sekitar set komponen yang kecil dan fokus:
- Backend NestJS (
schedule.service.ts) memiliki laluan snap, memoization kaskad, dan kontrak penulisan dengan MediaLive. - Kuiri pertindihan julat masa. Apabila lepas tiba, backend menarik setiap program sedia ada yang tetingkap masanya menyentuh julat kumpulan baru, ditambah buffer 6 saat di setiap sisi. Oleh kerana kuiri ini beroperasi pada julat masa dan bukannya tarikh kalendar, program silang tengah malam dikendalikan sama seperti mana-mana program lain โ tiada logik sempadan tarikh khas wujud di mana-mana dalam sistem.
- Garis masa gabungan. DTO program baru dan program sedia ada yang dikueri digabungkan menjadi satu senarai yang disusun. Laluan snap berjalan melawan garis masa gabungan ini.
shiftedExistingspeta. Untuk mana-mana program sedia ada yang disentuh oleh anjakan, peta ini menangkap masa mula dan tamat asalnya kali pertama ia disentuh โ dan tidak pernah menulis semula mereka pada sentuhan seterusnya. Struktur data ini adalah apa yang menjadikan kaskad berbilang langkah selamat.- Lambda
DELETE_PROGRAM. Untuk mana-mana program yang telah diubah yang telah disebarkan ke MediaLive, masa asalnya dihantar ke fungsi Lambda untuk pembersihan sebelum MongoDB dikemas kini. MIN_NEIGHBOUR_GAP_MS = 6000โ pemalar tunggal yang setiap peraturan, setiap kuiri pertindihan, dan setiap buffer keselamatan merujuk.
Keputusan Kejuruteraan Utama
1. Empat peraturan, satu laluan, tiada kes khas. Empat peraturan yang sama meliputi setiap senario yang boleh dicipta oleh pengendali: program baru yang dijatuhkan antara dua yang sedia ada, dua program baru yang bertentangan antara satu sama lain, atau program sedia ada yang ditolak ke dalam pertindihan oleh anjakan sebelumnya dalam lepas yang sama. Tiada laluan kod berasingan untuk mana-mana daripada ini โ setiap kes dikurangkan kepada "periksa jurang antara program bersebelahan dan guna peraturan."
2. Enam saat, bukan lima. MediaLive menguatkuasakan jarak minimum 5 saat antara tindakan jadual; menjadualkan dua pertukaran input 4.9 saat berasingan menyebabkan penolakan penyebaran. Sistem menguatkuasakan 6 saat โ margin keselamatan satu saat untuk hanyutan jam antara jam backend dan AWS. Mengemukakan tindakan pada tepat 5.000 saat, apabila jam pengekod membacanya sebagai 4.997 saat, menghasilkan penolakan berselang yang kelihatan seperti kegagalan rangkaian dan terasa seperti pepijat yang tidak dapat dihasilkan semula. Satu saat tambahan menukar mod kegagalan berselang kepada satu yang tidak pernah berlaku.
Ini datang dengan pertukaran yang disengajakan: lantai 6 saat bermakna jurang kecil bersebelahan 3 atau 4 saat ditutup kepada sifar dan bukannya dipelihara. Pertukaran itu diterima secara sengaja โ peralihan bersebelahan bersih di MediaLive, dan jurang 3 saat yang kelihatan cenderung kelihatan seperti gangguan kepada penonton tanpa mengira.
3. Memoization masa asal menjadikan kaskad selamat. Satu lepas boleh mencetuskan rantaian anjakan โ program A mengalihkan B, B mengalihkan C, C mengalihkan D. Panggilan pembersihan ke MediaLive mesti menyasarkan masa asal setiap program yang disebarkan, bukan masa anjakan kaskadnya; menggunakan masa yang salah menyebabkan MediaLive bertindak balas dengan "tiada tindakan ditemui," secara senyap gagal pembersihan. Laluan mengekalkan peta programId โ {oldStartTime, oldEndTime}, ditangkap kali pertama setiap program disentuh. Anjakan kaskad kemudian hanya mengemas kini garis masa dalam memori; asal yang diingati kekal tidak disentuh, dan pembersihan sentiasa menggunakan apa yang sebenarnya ada pada rekod MediaLive.
Diagram 2 ยท Contoh Kaskad

4. Pengawal tarikh lalu, dikuatkuasakan dalam dua fasa berasingan. Edit bertarikh lalu disekat dua kali, dengan sengaja:
- Fasa 0, sebelum laluan snap berjalan: mana-mana program baru dengan masa mula lebih awal daripada "sekarang" menolak keseluruhan kumpulan secara terang-terangan, dengan ralat yang jelas. Laluan snap tidak pernah berjalan melawan input yang mustahil.
- Fasa 4, selepas laluan snap: dua sub-kes berbeza dikendalikan secara berbeza. Program baru yang snap secara tidak sengaja ditarik ke masa lalu (jarang, tetapi mungkin pada sempadan jam masa permintaan) dipulihkan secara senyap kepada masa asalnya sebelum snap โ niat pengendali dipelihara, dan snap tidak diterapkan. Program sedia ada yang anjakan akan menolak ke masa lalu sebaliknya menolak keseluruhan kumpulan โ menyentuh program yang telah mula disiarkan tidak pernah menjadi sesuatu yang sistem akan menyerap secara senyap.
5. Kontrak penulisan Lambda-pertama, pangkalan data-kedua. Apabila snap mengalihkan program yang telah disebarkan ke MediaLive, MongoDB dan MediaLive sebentar tidak seiring, dan urutan penyelarasan adalah penting. Kontrak: Lambda pertama, MongoDB kedua. Backend memanggil DELETE_PROGRAM pada Lambda menggunakan masa asal program; jika mana-mana panggilan gagal, backend melempar sebelum sebarang penulisan pangkalan data berlaku. Hanya apabila setiap panggilan hapus berjaya, satu bulkWrite mengemas kini MongoDB dengan masa baru dan menetapkan semula isDeployed: false.
Ini menghasilkan satu invarian bersih: jika MongoDB menunjukkan program pada masa baru, MediaLive telah menerima pergerakan itu. Jika pengendali melihat ralat sebaliknya, tiada sistem disentuh. Tiada keadaan yang mungkin di mana MongoDB dan MediaLive secara senyap tidak bersetuju tentang masa program.
6. Hari reset mempunyai jaring keselamatan khususnya sendiri. "Hari reset" memadamkan setiap program pada saluran untuk hari kalendar tertentu โ operasi paling merosakkan dalam sistem โ jadi ia membawa dua perlindungan khusus.
- Buffer 2 minit (
SAFETY_BUFFER_MS = 120000) mengecualikan mana-mana program yang bermula dalam masa dua minit berikutnya, memberikan main balik langsung tetingkap rahmat supaya reset tidak pernah berlumba dengan program yang akan disiarkan. - Pemeliharaan bawa ke hadapan mengecualikan program yang bermula pada hari sebelumnya tetapi tumpah ke hari ini โ program tersebut milik jadual semalam, bukan hari ini.
Fallback yang baik juga tersedia: jika saluran tidak pernah disebarkan ke MediaLive sama sekali, Lambda mengembalikan rentetan ralat tertentu yang backend fahami, log sebagai no_infrastructure, dan kemudian melakukan penghapusan lembut hanya MongoDB. Reset masih berjaya; langkah AWS hanya menjadi tidak berfungsi.
Mengapa Gabungan Pilihan Reka Bentuk Ini
| Keputusan | Mengapa ia dibuat | Alternatif yang dipertimbangkan | Pertukaran yang diterima |
|---|---|---|---|
| Auto-selesaikan pada masa lepas vs. tolak-dan-minta | Menjaga seret dan lepas boleh digunakan pada skala; matematik snap manual tidak bertahan dalam senarai main yang berkembang | Tolak pada konflik, minta pengendali memperbaiki | Memerlukan sistem, bukan pengendali, untuk menjamin ketepatan |
| Lantai 6 saat vs. minimum 5 saat yang dinyatakan MediaLive | Menyerap hanyutan jam antara backend dan AWS, mencegah kegagalan penyebaran berselang | Menguatkuasakan tepat 5 saat | Jurang kecil (3โ4s) yang disengajakan disnap ke sifar dan bukannya dipelihara |
| Laluan laluan ke hadapan tunggal vs. penyelesaian konflik rekursif | Kaskad diselesaikan secara deterministik tanpa kebimbangan kedalaman rekursi | Anjakan dan semak semula rekursif | Memerlukan penyusunan garis masa yang disusun dengan teliti di hadapan |
| Lambda-pertama / DB-kedua vs. DB-pertama / Lambda-kedua | Menjamin MongoDB dan MediaLive tidak pernah tidak bersetuju secara senyap | Kemas kini MongoDB secara optimis, segerakkan MediaLive selepas | Sedikit latensi lebih tinggi bagi setiap program yang dialihkan dan disebarkan, sebagai pertukaran untuk risiko hanyutan sifar |
Apa yang Masih Dipantau
Kejuruteraan yang jujur bermaksud menamakan jurang yang masih terbuka, bukan hanya yang telah diselesaikan.
- Edit serentak pada saluran yang sama. Jika dua pengendali mengklik Deploy pada saluran yang sama dalam beberapa ratus milisaat antara satu sama lain, kedua-duanya akan memuatkan snapshot yang sama, kedua-duanya akan menjalankan laluan snap secara bebas, dan kedua-duanya akan menulis ke MongoDB. Tiada kunci per saluran atau pemeriksaan versi optimis hari ini. Mitigasi semasa adalah operasi โ satu pengendali memiliki satu saluran pada satu masa โ sementara pembaikan teknikal, medan versi pada dokumen saluran yang diperiksa pada masa penulisan, ada dalam peta jalan.
- Tiada maklum balas dalam UI untuk apa yang disnap. Apabila laluan mengalihkan program sebanyak tiga saat, pandangan pengendali menyegarkan kepada keadaan yang diperbetulkan, tetapi belum lagi menampilkan apa yang bergerak dan mengapa. Data sudah ada dalam muatan respons; pemberitahuan, bar sisi, atau pandangan perbezaan dirancang untuk iterasi seterusnya UI penjadual.
Keputusan
- Pengendali boleh melepaskan program di mana sahaja pada garis masa, dan sistem menjadikan jadual yang terhasil sah dalam satu laluan deterministik โ tiada mod konflik, tiada dinding ralat, tiada matematik snap manual.
- Satu algoritma empat-peraturan meliputi setiap kes โ baru-vs-baru, baru-vs-sedia ada, dan anjakan kaskad merentasi sempadan hari โ tanpa kes khas mana-mana daripadanya.
- Program silang tengah malam dan peralihan DST mengalir melalui kuiri pertindihan julat masa yang sama seperti mana-mana kes lain; tiada "laluan kod tengah malam" berasingan untuk diselenggara.
- Hari reset tidak boleh secara tidak sengaja mengambil program langsung dari udara โ buffer 2 minit dan pemeliharaan bawa ke hadapan terpakai pada setiap saluran, setiap masa.
- Kontrak Lambda-pertama / pangkalan data-kedua menjadikan hanyutan jadual senyap mustahil: MongoDB dan MediaLive dijamin bersetuju, atau pengendali melihat ralat yang jelas.
MIN_NEIGHBOUR_GAP_MSadalah satu-satunya tombol yang boleh disesuaikan. Setiap margin keselamatan, setiap peraturan snap, dan setiap tetingkap pertindihan merujuknya, jadi menyesuaikan definisi platform "sah" adalah perubahan satu baris.
Pemikiran Akhir
Perkara yang paling menarik tentang sistem ini bukanlah mana-mana peraturan tunggal โ ia adalah betapa sedikit peraturan yang diperlukan. Empat syarat pada nilai jurang, diterapkan dalam satu laluan ke hadapan, meliputi setiap konflik yang boleh dicipta oleh pengendali, termasuk kaskad berbilang langkah merentasi sempadan tengah malam. Itu adalah hasil reka bentuk yang disengajakan: kerumitan ditolak untuk mendapatkan peraturan yang betul sekali, dan bukannya untuk menangani senarai kes khas yang semakin berkembang.
Pelajaran yang lebih luas ini menggeneralisasikan melebihi perisian penjadualan: apabila sistem mempunyai kekangan luaran yang ketat โ jarak minimum pengekod, jaminan konsistensi pangkalan data, siaran langsung yang tidak boleh disiarkan semula โ tempat paling selamat untuk menguatkuasakan kekangan tersebut adalah dalam sebilangan kecil peraturan deterministik yang diterapkan secara konsisten, bukan dalam pengendalian ad hoc yang tersebar di seluruh pangkalan kod. Dan apabila dua sistem rekod (di sini, MongoDB dan MediaLive) mesti kekal selari, menyusun penulisan supaya kegagalan sentiasa meninggalkan mereka dalam keadaan yang diketahui dan bersetuju adalah berbaloi dengan latensi tambahan yang dikenakan.
Tentang MicrocosmWorks
Di MicrocosmWorks, kami membina perisian gred pengeluaran untuk organisasi yang menyelesaikan masalah kejuruteraan yang kompleks.
Kepakaran kami termasuk aplikasi AI, platform SaaS, perisian perusahaan, sistem cloud-native, teknologi media, dan seni bina backend tersuai.
Melalui blog kejuruteraan kami, kami berkongsi pelajaran praktikal yang dipelajari daripada merancang dan mengendalikan sistem pengeluaran dunia sebenar.
Teruskan Membaca
Jika anda menikmati artikel ini, anda mungkin juga mendapati topik berikut berguna:

