Kapag tinanong mo ang sinumang operator ng live-TV kung ano ang nais nilang makita sa isang tool sa pag-iskedyul, halos palagi silang sasabihin, "Hayaan mo akong bumuo ng channel sa paraan ng pag-oorganisa ko ng mga file sa isang folder. I-drag ang isang programa, i-drop ito kung saan ko gusto, tapos na.
Ang problema ay ang iskedyul ng channel ay hindi isang folder. Ito ay isang legal na dokumento na may mahigpit na paghihigpit. Hindi maaaring magsabay ang dalawang programa. Hindi maaaring lumipat ang encoder ng inputs nang mas mabilis kaysa bawat limang segundo. Hindi maaaring i-edit ang isang programang nagsimula na. At ang isang pelikulang lumampas sa hatinggabi ay kailangang ituring bilang isang programa, hindi hinati sa hangganan ng araw.
Bawat aksyon ng drag-and-drop ay isang potensyal na paglabag sa constraint na naghihintay mangyari. Ito ang kuwento ng engineering kung paano ginagawang legal na timeline ng channel sa AWS MediaLive ng scheduler ng mStudio ang operator-friendly na drag-and-drop โ kasama ang sandaling ihulog ng isang operator ang isang programa direkta sa ibabaw ng isa pa โ at kung bakit awtomatikong nireresolba ng system ang mga salungatan na iyon sa halip na bigyan ang operator ng error at palaisipan upang lutasin.
Mabilis na Pangkalahatang-ideya
| Aspekto | Detalye |
|---|---|
| Domain | Pag-iskedyul ng Drag-and-drop para sa mga live na FAST channels sa AWS MediaLive |
| Pagresolba ng Salungatan | Auto-shift sa pamamagitan ng 4-rule snap algorithm |
| Minimum na agwat sa kapitbahay | 6 na segundo (5s minimum ng MediaLive + 1s safety para sa clock-drift) |
| Pangangasiwa ng Cascade | Ang mga orihinal na oras ay minemo sa unang paghawak, kaya ang mga chained shifts ay nagbubunga ng isang malinis na cleanup call bawat programa |
| Past-date safety | Two-phase guard โ pagtanggi ng input, kasama ang silent post-snap revert |
| Reset-day safety | 2-minutong live-playback buffer, kasama ang pagpapanatili ng carry-over |
| Status | Nasa produksyon |
Ang Problema sa Negosyo: Isang Kalendaryo Na Hindi Kalendaryo
Ang pag-iskedyul ng channel ay mukhang calendar software. Inaasahan ng mga operator na ito ay kumilos tulad ng isa โ i-drag ang isang pelikula sa isang 9 PM slot, i-slide ang mga programa sa timeline, mag-batch-add ng isang serye at panoorin ang mga episode na magkakasunod. Ngunit ang isang live na iskedyul ng channel ay nagdadala ng mga paghihigpit na hindi taglay ng isang kalendaryo:
- Hindi pinahihintulutan ang magpatong-patong ang mga programa. Ang Live TV ay nagpapalabas ng eksaktong isang bagay sa isang pagkakataon.
- Ang encoder ay may minimum na espasyo ng aksyon. Hindi lilipat ang AWS MediaLive ng inputs nang mas mabilis kaysa bawat 5 segundo. Mag-iskedyul ng dalawang programa na may agwat na 4 na segundo, at tatanggihan ang deploy.
- Hindi maaaring i-edit ang mga nakaraang programa. Lumipas na ang air time; ang mga bits ay nasa screen na ng mga manonood.
- Ang mga programang lumalagpas sa hatinggabi ay isang unit. Ang isang pelikulang tumatakbo mula 23:30 hanggang 01:15 ay kailangang pangasiwaan bilang isang programa, hindi dalawang kalahating-programa na hinati sa hangganan ng araw.
Ang "halos magpatong" na dalawang segundo ay hindi error ng operator โ ito ay ang natural na resulta ng pag-drag ng dalawang programa na halos, ngunit hindi eksakto, magkasya. Ang tunay na hamon sa engineering ay ang pagsasalin ng "i-drag ang isang pelikula sa 9 PM" sa "isang legal na iskedyul ng channel." Kung mali ang pagkakagawa, ang operator ay maaaring makaranas ng error sa bawat paghulog, o โ mas masahol pa โ matutuklasan sa air time na tahimik na tinanggihan ng encoder ang bahagi ng iskedyul.
Ano ang Ibig Sabihin ng "Legal" sa AWS MediaLive
Upang maging legal ang isang iskedyul sa MediaLive, ang magkakalapit na programa ay dapat na:
- Magkakasunod โ walang agwat sa pagitan nila, o
- Pinaghiwalay ng hindi bababa sa 5 segundo โ ang minimum na espasyo ng aksyon ng encoder.
Ang bitag ay ang lahat ng nasa pagitan. Isang 1-segundong agwat, isang 3-segundong agwat, isang 4.9-segundong agwat โ lahat ng ito ay mukhang maayos sa isang UI, at lahat ng ito ay tinatanggihan sa deploy time. Mas masahol pa, ang pagtanggi ay hindi isang malinis, atomic failure; maaari itong magresulta sa isang partially-deployed na channel, kung saan ang ilang mga aksyon sa iskedyul ay napunta sa MediaLive at ang iba ay hindi.
Magdagdag ng 1-segundong safety margin para sa clock drift sa pagitan ng mga application server at AWS, at ang praktikal na palapag ay magiging 6 na segundo, hindi 5. Ang nag-iisang numerong ito โ MIN_NEIGHBOUR_GAP_MS = 6000 โ ang nag-iisang constant na pinagbasehan ng buong sistema ng pagresolba ng salungatan.
Bakit Nabibigo ang mga Malinaw na Pamamaraan
Bago tuluyang magpasya sa awtomatikong pagresolba, ilang mas malinaw na estratehiya ang isinasaalang-alang at tinanggihan:
"Tangggihan ang anumang hindi pagkakasundo at hilingin na ang operator ang magresolba nito." Dahil dito, kailangang manu-manong gawin ng mga operator ang snap math sa bawat paghulog. Ang isang limang-segundong pag-drag ay nagiging isang limang-minutong palaisipan, at ang palaisipan ay nagiging mas mahirap habang lumalaki ang playlist. Sa praktika, ganap na tinatalikdan ng mga operator ang drag-and-drop at bumabalik sa mga spreadsheet.
"I-snap ang lahat sa 5-minutong hangganan upang walang magpatong-patong." Nilulutas nito ang teknikal na problema sa pamamagitan ng pagsira sa intensyon ng operator. Ang isang programa na dapat magsimula sa 21:03:15 ay hindi dapat tahimik na tumalon sa 21:05:00. Ang iskedyul ay sa operator, hindi sa isang rounding function.
"Hanapin ang mga salungatan sa deploy time sa halip na drop time." Mas mabilis ang pakiramdam nito sa UI, ngunit inililipat nito ang pagkabigo sa pinakamasamang posibleng sandali. Sa oras na mag-click ang operator ng Deploy at makita ang "schedule rejected at program 47," mental na silang lumipat mula sa pag-edit na nagdulot nito.
"Payagan ang micro-gaps sa UI at hayaan ang MediaLive na tanggihan ang mga ito." Ibinabalik nito ang opaque encoder errors nang direkta sa operator, at maaaring iwan ang channel sa isang half-deployed state na talagang mahirap i-recover.
Ang solusyon na talagang gumana ay ang awtomatikong pagresolba ng mga salungatan, sa drop time, gamit ang deterministic na mga panuntunan โ at agad na ipinapakita ang naitamang timeline sa operator.
Ang Solusyon: Isang Four-Rule Snap Algorithm
Sa bawat paghulog, sinusuri ng isang snap algorithm ang bawat pares ng magkakalapit na programa sa apektadong channel โ mga pares ng bago-sa-bago, bago-sa-umiiral, o umiiral-sa-umiiral na ang agwat ay nagbago dahil sa paghulog โ at naglalapat ng eksaktong isa sa apat na panuntunan batay sa agwat sa pagitan nila:
- Agwat = 0 โ walang aksyon. Ang magkakasunod ay legal, at halos tiyak na iyon ang intensyon ng operator.
- Agwat โฅ 6 segundo โ walang aksyon. Sadyang nag-iwan ng espasyo ang operator, malamang para sa isang slate o ad pod.
- 0 < agwat < 6 segundo โ iurong ang pangalawang programa pabalik upang isara ang agwat sa zero.
- Negatibong agwat (overlap) โ iurong ang pangalawang programa pasulong sa dami ng overlap.
Mahalaga, pinoproseso ng algorithm ang magkakalapit na pares sa isang single forward pass sa pinagsunod-sunod na timeline. Ang bawat shifted na programa ay agad na nagiging "nakaraang" item para sa susunod na paghahambing โ kaya ang isang paghulog na nag-trigger ng chain reaction ng shifts ay nareresolba sa isang linear walk, nang walang kinakailangang recursion.
Diagram 1 ยท Ang Snap Decision Tree

Arkitektura ng System
Ang scheduler ay binuo sa paligid ng isang maliit, nakatutok na set ng mga bahagi:
- NestJS backend (
schedule.service.ts) ang nagmamay-ari ng snap walk, ang cascade memoization, at ang write contract sa MediaLive. - Time-range overlap query. Kapag dumating ang isang paghulog, kinukuha ng backend ang bawat umiiral na programa na ang time window ay humahawak sa range ng bagong batch, kasama ang isang 6-segundong buffer sa bawat panig. Dahil ang query na ito ay nagpapatakbo sa time ranges sa halip na mga petsa ng kalendaryo, ang mga programang lumalagpas sa hatinggabi ay pinangangasiwaan nang magkapareho sa anumang iba pang programa โ walang espesyal na date-boundary logic na umiiral saanman sa system.
- Merged timeline. Ang mga bagong program DTOs at ang mga queried na umiiral na programa ay pinagsama sa isang solong pinagsunod-sunod na listahan. Ang snap walk ay tumatakbo laban sa pinagsamang timeline na ito.
shiftedExistingsmap. Para sa anumang umiiral na programa na nahawakan ng isang shift, kinukuha ng map na ito ang orihinal nitong oras ng pagsisimula at pagtatapos sa unang pagkakataong nahawakan ito โ at hindi kailanman inoo-overwrite ang mga ito sa mga susunod na paghawak. Ang iisang data structure na ito ang dahilan kung bakit ligtas ang multi-step cascades.- Lambda
DELETE_PROGRAM. Para sa anumang na-shift na programa na na-deploy na sa MediaLive, ang orihinal nitong mga oras ay ipinapadala sa isang Lambda function para sa paglilinis bago i-update ang MongoDB. MIN_NEIGHBOUR_GAP_MS = 6000โ ang nag-iisang constant na nire-reference ng bawat panuntunan, bawat overlap query, at bawat safety buffer.
Pangunahing Desisyon sa Engineering
1. Apat na panuntunan, isang lakad, walang espesyal na kaso. Ang parehong apat na panuntunan ay sumasaklaw sa bawat senaryo na maaaring likhain ng isang operator: isang bagong programa na inihulog sa pagitan ng dalawang umiiral na programa, dalawang bagong programa na magkasalungat sa isa't isa, o isang umiiral na programa na itinulak sa overlap ng mas maagang shift sa parehong paghulog. Walang hiwalay na code path para sa alinman sa mga ito โ bawat kaso ay nababawasan sa "suriin ang agwat sa pagitan ng magkakalapit na programa at ilapat ang panuntunan."
2. Anim na segundo, hindi lima. Nagpapatupad ang MediaLive ng 5-segundong minimum na espasyo sa pagitan ng mga aksyon sa iskedyul; ang pag-iskedyul ng dalawang input switches na 4.9 segundo ang pagitan ay nagiging sanhi ng pagtanggi sa deploy. Nagpapatupad ang system ng 6 na segundo โ isang isang-segundong safety margin para sa clock drift sa pagitan ng clock ng backend at ng AWS. Ang pagsumite ng aksyon sa eksaktong 5.000 segundo, kapag binasa ito ng clock ng encoder bilang 4.997 segundo, ay nagbubunga ng pasulput-sulpot na pagtanggi na mukhang network failures at pakiramdam ay hindi ma-reproduce na mga bug. Ang dagdag na segundo ay ginagawang isang failure mode na hindi kailanman mangyayari ang isang pasulput-sulpot na failure mode.
Ito ay may kaakibat na sinadyang tradeoff: ang isang 6-segundong palapag ay nangangahulugang ang maliliit na magkakasunod na agwat ng 3 o 4 na segundo ay isinasara sa zero sa halip na panatilihin. Sinadyang tanggapin ang tradeoff na iyon โ malinis ang back-to-back transitions sa MediaLive, at ang isang nakikitang 3-segundong agwat ay kadalasang mukhang glitch sa mga manonood.
3. Ang original-time memoization ay nagpapaligtas sa cascades. Ang isang solong paghulog ay maaaring mag-trigger ng isang chain ng shifts โ program A shifts B, B shifts C, C shifts D. Ang cleanup call sa MediaLive ay dapat mag-target ng orihinal na deployed time ng bawat programa, hindi ang cascade-shifted time nito; ang paggamit ng maling oras ay nagiging sanhi ng pagtugon ng MediaLive ng "no action found," na tahimik na nagpapabigo sa cleanup. Pinapanatili ng walk ang isang map ng programId โ {oldStartTime, oldEndTime}, na kinukuha sa unang pagkakataong mahawakan ang bawat programa. Ang mga susunod na cascade shifts ay nag-u-update lamang ng in-memory timeline; ang memoized originals ay nananatiling hindi nagalaw, at ang cleanup ay palaging gumagamit ng eksakto kung ano ang aktwal na nasa record ng MediaLive.
Diagram 2 ยท Isang Halimbawa ng Cascade

4. Past-date guards, ipinatutupad sa dalawang hiwalay na yugto. Ang mga past-dated edits ay dalawang beses na hinaharangan, sinasadya:
- Yugto 0, bago tumakbo ang snap walk: anumang bagong programa na may start time na mas maaga kaysa "ngayon" ay ganap na tinatanggihan ang buong batch, na may malinaw na error. Ang snap walk ay hindi kailanman tumatakbo laban sa isang imposibleng input.
- Yugto 4, pagkatapos ng snap walk: dalawang magkaibang sub-case ang pinangangasiwaan nang magkaiba. Ang isang bagong programa na hindi sinasadyang nahila ng snap sa nakaraan (bihira, ngunit posible sa mga hangganan ng orasan sa request-time) ay tahimik na ibinabalik sa orihinal nitong, pre-snap time โ pinapanatili ang intensyon ng operator, at ang snap ay hindi lamang inilalapat. Ang isang umiiral na programa na itutulak ng isang shift sa nakaraan ay sa halip ay tinatanggihan ang buong batch โ ang paghawak sa isang programa na nagsimula nang umere ay hindi kailanman tahimik na sisisipsipin ng system.
5. Isang Lambda-first, database-second na write contract. Kapag ang isang snap ay nag-shift ng isang programa na na-deploy na sa MediaLive, ang MongoDB at MediaLive ay panandaliang hindi naka-sync, at mahalaga ang pagkakasunud-sunod ng reconciliation. Ang kontrata: Lambda muna, MongoDB pangalawa. Tinatawag ng backend ang DELETE_PROGRAM sa Lambda gamit ang orihinal na oras ng programa; kung may tawag na mabibigo, magtatapon ang backend bago pa man mangyari ang anumang database write. Kapag lamang nagtagumpay ang bawat delete call, isang solong bulkWrite ang mag-u-update sa MongoDB gamit ang mga bagong oras at magre-reset ng isDeployed: false.
Nagbubunga ito ng isang malinis na invariant: kung ang MongoDB ay nagpapakita ng isang programa at isang bagong oras, tinanggap na ng MediaLive ang paglipat na iyon. Kung ang operator ay makakita ng error, walang system ang nahawakan. Walang posibleng estado kung saan ang MongoDB at MediaLive ay tahimik na hindi nagkakasundo tungkol sa oras ng programa.
6. Ang reset day ay may sariling dedicated safety net. Ang "reset day" ay nagde-delete ng bawat programa sa isang channel para sa isang partikular na araw ng kalendaryo โ ang nag-iisang pinakamapaminsalang operasyon sa system โ kaya mayroon itong dalawang partikular na proteksyon.
- Ang isang 2-minutong buffer (
SAFETY_BUFFER_MS = 120000) ay nagpapalaya sa anumang programang magsisimula sa loob ng susunod na dalawang minuto, na nagbibigay sa live playback ng isang grace window upang ang isang reset ay hindi kailanman makipaglaban sa isang programang malapit nang umere. - Carry-over preservation ay nagbubukod sa mga programang nagsimula noong nakaraang araw ngunit tumatagos hanggang ngayon โ ang mga iyon ay kabilang sa iskedyul ng kahapon, hindi ng ngayon.
Mayroon ding magandang fallback na opsyon: kung ang isang channel ay hindi pa na-deploy sa MediaLive, ibinabalik ng Lambda ang isang partikular na error string na naiintindihan ng backend, itinatala bilang no_infrastructure, at pagkatapos ay gumaganap ng isang MongoDB-only soft deletion. Nagtagumpay pa rin ang pag-reset; ang hakbang sa AWS ay nagiging isang no-op lamang.
Bakit ang Kombinasyon na Ito ng mga Pagpipilian sa Disenyo
| Desisyon | Bakit ginawa | Alternatibong isinaalang-alang | Tinanggap na Trade-off |
|---|---|---|---|
| Awtomatikong pagresolba sa drop time vs. tanggihan-at-tanungin | Pinapanatili ang drag-and-drop na magagamit sa scale; ang manual snap math ay hindi nabubuhay sa lumalaking playlist | Tanggihan sa salungatan, hilingin sa operator na ayusin | Nangangailangan ng system, hindi ang operator, upang magarantiya ang kawastuhan |
| 6-segundong palapag vs. nakasaad na 5-segundong minimum ng MediaLive | Sumisipsip ng clock drift sa pagitan ng backend at AWS, pinipigilan ang pasulput-sulpot na deploy failures | Ipatupad nang eksakto ang 5 segundo | Ang maliliit (3โ4s) na sinadyang agwat ay isinasara sa zero sa halip na panatilihin |
| Single forward-pass walk vs. recursive conflict resolution | Ang cascades ay nareresolba nang deterministically nang walang pag-aalala sa recursion depth | Recursive shift-and-recheck | Nangangailangan ng maingat na pag-order ng sorted timeline sa simula |
| Lambda-first / DB-second vs. DB-first / Lambda-second | Ginagarantiya na ang MongoDB at MediaLive ay hindi kailanman tahimik na hindi magkakasundo | I-update ang MongoDB nang optimistically, i-sync ang MediaLive pagkatapos | Bahagyang mas mataas na latency bawat shifted-and-deployed program, kapalit ng zero drift risk |
Ano ang Patuloy na Binabantayan
Ang tapat na engineering ay nangangahulugang pagtukoy sa mga agwat na nananatiling bukas, hindi lamang sa mga nalutas na.
- Magkasabay na pag-edit sa iisang channel. Kung dalawang operator ang mag-click ng Deploy sa parehong channel sa loob ng ilang daang millisecond ng isa't isa, pareho silang maglo-load ng parehong snapshot, pareho silang magpapatakbo ng snap walk nang independyente, at pareho silang magsususlat sa MongoDB. Walang per-channel lock o optimistic version check ngayon. Ang kasalukuyang mitigation ay operational โ isang operator ang nagmamay-ari ng isang channel sa isang pagkakataon โ habang ang teknikal na solusyon, isang version field sa channel document na sinusuri sa write time, ay nasa roadmap.
- Walang in-UI feedback para sa kung ano ang na-snap. Kapag inilipat ng walk ang isang programa ng tatlong segundo, nagre-refresh ang view ng operator sa naitamang estado, ngunit hindi pa ipinapakita kung ano ang gumalaw at bakit. Umiiral na ang data sa response payload; isang toast, sidebar, o diff view ang pinaplano para sa susunod na iteration ng scheduler UI.
Mga Resulta
- Maaaring maghulog ang mga operator ng programa kahit saan sa timeline, at ginagawa ng system na legal ang nabuong iskedyul sa isang deterministic pass โ walang conflict modals, walang error walls, walang manual snap math.
- Saklaw ng isang four-rule algorithm ang bawat kaso โ new-vs-new, new-vs-existing, at cascading shifts sa mga day boundary โ nang walang special-casing sa alinman sa mga ito.
- Ang mga programang lumalagpas sa hatinggabi at mga paglipat ng DST ay dumadaan sa parehong time-range overlap query tulad ng anumang iba pang kaso; walang hiwalay na "midnight code path" na panatilihin.
- Hindi maaaring aksidenteng alisin ng reset day ang isang live na programa sa ere โ ang 2-minutong buffer at carry-over preservation ay nalalapat sa bawat channel, sa bawat pagkakataon.
- Ang Lambda-first / database-second contract ay nagpapawalang-saysay sa silent schedule drift: ginagarantiya na magkakasundo ang MongoDB at MediaLive, o makikita ng operator ang isang explicit na error.
Ang
MIN_NEIGHBOUR_GAP_MSang nag-iisang tunable knob. Bawat safety margin, bawat snap rule, at bawat overlap window ay nire-reference ito, kaya ang pag-aayos sa depinisyon ng platform ng "legal" ay isang one-line change.
Panghuling Saloobin
Ang pinakakawili-wiling bagay tungkol sa system na ito ay hindi ang alinmang nag-iisang panuntunan โ kundi kung gaano kakaunting panuntunan ang kailangan. Apat na kondisyon sa isang gap value, na inilapat sa isang forward pass, ay sumasaklaw sa bawat salungatan na maaaring likhain ng isang operator, kasama ang multi-step cascades sa mga midnight boundaries. Iyon ay isang sinadyang resulta ng disenyo: ang pagiging kumplikado ay itinulak sa pagkuha ng tamang mga panuntunan nang isang beses, sa halip na sa paghawak ng isang lumalaking listahan ng mga special cases.
Ang mas malawak na aralin ay nagpapalawak sa nakaraang scheduling software: kapag ang isang system ay may mahigpit na panlabas na paghihigpit โ ang minimum na espasyo ng encoder, ang consistency guarantees ng database, isang live broadcast na hindi maaaring alisin sa ere โ ang pinakaligtas na lugar upang ipatupad ang mga paghihigpit na iyon ay sa isang maliit na bilang ng deterministic na mga panuntunan na inilapat nang pare-pareho, hindi sa ad hoc na paghawak na nakakalat sa buong codebase. At kapag ang dalawang system of record (dito, MongoDB at MediaLive) ay dapat manatiling naka-sync, ang pag-order ng mga writes upang ang failure ay palaging nag-iiwan sa kanila sa isang kilala, nagkakasundong estado ay sulit sa karagdagang latency na kaakibat nito.
Tungkol sa MicrocosmWorks
Sa MicrocosmWorks, gumagawa kami ng production-grade software para sa mga organisasyong lumulutas ng kumplikadong problema sa engineering.
Kasama sa aming kadalubhasaan ang AI applications, SaaS platforms, enterprise software, cloud-native systems, media technology, at custom backend architecture.
Sa pamamagitan ng aming engineering blog, ibinabahagi namin ang mga praktikal na aral na natutunan mula sa pagdidisenyo at pagpapatakbo ng mga real-world production system.
Magpatuloy sa Pagbabasa
Kung nasiyahan ka sa artikulong ito, maaari mo ring makita ang mga paksang ito na kapaki-pakinabang:

