Problemet var inte fem dåliga timers. Problemet var att de konkurrerade om samma öra.
Vid det här laget hade jag hourly, station-ID, banter, programfeatures, generativa skills och jinglar. Första generationens lösning var naturlig: varje sak har sin egen timer.
Det fungerar tills två saker vill samma minut. Flyttar jag station-ID från :00 till :15 har jag bara flyttat konflikten. Lägger jag banter på :20 kan en feature fortfarande råka gå :19:40 och blockera det.
Jag byggde därför Relay 7 Talk Scheduler med en central slottabell.
[
{ kind:"programme", priority:1, window:1, gap:0, air:"immediate" },
{ kind:"hourly", priority:2, window:10, gap:3, air:"immediate" },
{ kind:"banter", priority:3, window:10, gap:5, air:"immediate" },
{ kind:"station-id",priority:4, window:10, gap:3, air:"next-track" },
{ kind:"segment", priority:5, window:1, gap:0, role:"fill" },
{ kind:"jingle", priority:6, window:1, gap:3, role:"fill" }
]Skillnaden är att ett segment som förlorar en minut kan vänta inom sitt fönster. Schedulern kan logga varför: senaste fristående prat var för nyligen, en annan slot tog minuten eller ett redan renderat klipp väntar på boundary.
Det blev mycket mer robust än att varje modul gissar själv.
Den viktiga delen var inte vem som hade rätt först
Det intressanta med referensmodulen var att två kodbaser som utvecklats på olika håll nådde samma arkitekturella slutsats. Det är ett starkt tecken på att problemet verkligen ligger i domänen och inte bara i en specifik implementation.
För mig blev det en bekräftelse på att central arbitration var rätt investering även om den krävde mer kod än en snabb timerpatch.
Talk Scheduler fick bli ren beslutslogik
Jag ville kunna testa schedulern utan att köra Gemma 3, Westin-AI eller Broadcast. Därför byggdes själva planeringen som så ren logik som möjligt: klocka, öppna slots, senaste talk, pending state och policyresultat in; fire, wait eller miss ut.
Det gör att jag kan simulera en hel timme på millisekunder och fånga regressioner. Om jag ändrar ett fönster kan ett test visa att station-ID plötsligt kan kollidera med hourly.
Det här är ett återkommande mönster i den nyare kodbasen: separera beslut från effekt. Först bestäm vad som ska hända. Sedan kör nät, modell och queue.