Een import die uren duurt, een rapport dat meerdere bronnen raadpleegt of een taak die integraties coördineert, kan nog lang resources blijven verbruiken nadat de taak niet meer nuttig is. Zonder expliciete limieten is het bovendien moeilijk vast te stellen of de taak bezig, vastgelopen of onvolledig is. Tijdslimieten ontwerpen voor langlopende PHP-processen vereist dat wordt bepaald hoe lang elke fase mag duren, hoe het werk wordt gestopt en welke status behouden blijft als de uitvoering wordt onderbroken.
Het doel is niet om één getal voor het hele proces op te leggen. Het gaat erom een samenhangend budget van begin tot eind vast te stellen, dit door te geven aan afhankelijke bewerkingen en ervoor te zorgen dat de eindstatus weergeeft wat er is gebeurd. Een time-out, een aangevraagde annulering en een geforceerde beëindiging zijn verschillende situaties en moeten ook als zodanig worden behandeld.
Waarom een expliciete limiet nodig is

Een proces zonder deadline kan geheugen, verbindingen en uitvoeringscapaciteit onbeperkt bezet houden. Ook kan een taak als actief gemarkeerd blijven terwijl deze geen voortgang meer boekt. In een omgeving met workers wordt het probleem groter: een vastgelopen uitvoering bezet een worker en kan daaropvolgende taken vertragen.
PHP- of serverlimieten vervangen geen applicatiebeleid. Zo kan max_execution_time de uitvoering van een script beperken, maar dit weerspiegelt niet noodzakelijkerwijs hoe lang de bedrijfsvoering bereid is te wachten. Bovendien kunnen de limieten van de webserver, PHP-FPM, de wachtrijbeheerder, de HTTP-client en de database onafhankelijk van elkaar ingrijpen. Als ze verschillen, kan één laag het werk beëindigen zonder dat een andere de bijbehorende status kan opslaan.
Breng eerst in kaart waar het proces wordt uitgevoerd en welke componenten het kunnen stoppen. Een CLI-taak, een queue worker en een webverzoek hebben verschillende mechanismen en gevolgen. De applicatielimiet moet naast die externe controles bestaan en er niet op vertrouwen dat een ervan de beëindiging zelfstandig afhandelt.
Maak onderscheid tussen time-out, deadline en annulering
- Time-out voor een bewerking: de maximale tijd die een specifieke aanroep mag duren, zoals een query of HTTP-verzoek.
- Globale deadline: het uiterste tijdstip voor het volledige proces. De fasen delen de resterende tijd, in plaats van dat elke fase de volledige termijn krijgt.
- Aangevraagde annulering: een expliciet besluit om het werk te stoppen, bijvoorbeeld omdat een gebruiker de taak heeft geannuleerd of het systeem deze uit een queue heeft verwijderd.
Een time-out geeft aan dat een bewerking niet binnen het beschikbare budget is afgerond. Dat betekent op zichzelf niet dat het hele proces moet stoppen: dat hangt af van de fase en de productregels. Annulering is daarentegen een controlesignaal dat het proces moet controleren en afhandelen zodra dat veilig kan. Geen van beide garandeert dat een besturingssysteem of supervisor een uitvoering op een exact moment stopt; een geforceerde beëindiging kan tussen controles plaatsvinden.
Geef de deadline weer als een absoluut tijdstip of als resterende tijd die wordt berekend op basis van een monotone klok. Controleer voordat een fase begint of er nog tijd over is. Dit voorkomt dat een reeks bewerkingen met afzonderlijke time-outs veel meer tijd verbruikt dan de globale deadline toelaat. Encapsuleer de berekening en de controle op annulering in PHP in een gedeeld object of service, in plaats van vergelijkingen op verschillende plekken te dupliceren.
Stem fasen en afhankelijkheden af op de resterende tijd
Splits het proces op in waarneembare fasen, bijvoorbeeld lezen, transformeren, schrijven en externe coördinatie. Stel per fase een tijdslimiet vast die de globale deadline niet overschrijdt. Niet alle fasen hoeven dezelfde tijdslimiet te hebben: een fase met begrensd lokaal werk kan een andere limiet nodig hebben dan een aanroep naar een externe service.
Stel bij het aanroepen van een afhankelijkheid de time-out in op de minimumwaarde van de operationele time-out en de resterende tijd van het proces. Stel verbindings- en leeslimieten afzonderlijk in als de library dat ondersteunt. Een snelle verbinding voorkomt niet dat het antwoord te lang op zich laat wachten, en een lees-time-out omvat niet noodzakelijkerwijs alle voorafgaande tijd. Pas hetzelfde principe toe op SQL-queries, opslagbewerkingen en subprocessen, met behulp van de controles die elke client biedt.
Als een bewerking geen annulering ondersteunt, presenteer deze dan niet alsof ze onmiddellijk kan worden onderbroken. Beperk de wachttijd, isoleer de bewerking in een aparte werkeenheid of ontwerp de workflow zo dat vóór en na de bewerking op annulering wordt gecontroleerd. Bewaar voor subprocessen de benodigde identifier om beëindiging aan te vragen en controleer of het proces daadwerkelijk is beëindigd; een signaal versturen is niet hetzelfde als bevestigen dat het proces is gestopt.
Stop het werk en laat een begrijpelijke status achter
Start geen nieuwe fasen wanneer de deadline verstrijkt of een annuleringsverzoek binnenkomt. Voer op veilige punten de noodzakelijke lokale handelingen uit om het resultaat vast te leggen en maak beheersbare resources vrij, zoals cursors of tijdelijke bestanden. Het opruimblok mag niet proberen het resterende werk te beëindigen: ook de uitvoering van dit blok moet een beperkte duur hebben en de oorzaak van de stopzetting niet verhullen.
Sla de taakstatus op en koppel deze aan een stabiele identifier. Registreer ten minste verschillende statussen, bijvoorbeeld running, completed, cancelled en timed_out, evenals de huidige fase en relevante tijdstempels. Voeg een voor operators leesbare reden toe, zonder onnodige gevoelige gegevens op te slaan. Werk de status waar mogelijk atomair bij en houd er rekening mee dat het proces kan stoppen voordat deze update is voltooid.
De aanroeper van de taak moet onderscheid kunnen maken tussen ‘geannuleerd’ en ‘mislukt vanwege de deadline’. Als de status na een abrupte beëindiging nog niet kan worden bevestigd, geef deze dan weer als onbekend of als verificatie in behandeling, niet als voltooid. Neem duur, fase en type stopzetting op in metrics en gestructureerde logs; vermijd het loggen van geheimen, privé-inhoud of traces zonder toegangscontrole.
Bepaal of gedeeltelijke effecten kunnen worden hervat
Een onderbreking kan plaatsvinden nadat gegevens zijn weggeschreven, maar voordat is geregistreerd dat de fase is voltooid. Daarom komt bij de beslissing of hervatten mogelijk is meer kijken dan alleen het fasenummer opslaan: er moet worden vastgesteld welke effecten mogelijk zijn opgetreden. Voor lokale bewerkingen kan een transactie gerelateerde wijzigingen bundelen, als de duur en de database-engine dit toelaten. Houd geen transactie open tijdens een lange externe aanroep.
Leg bij batchverwerking voltooide eenheden vast met een stabiele sleutel en bepaal wanneer een eenheid daadwerkelijk is bevestigd. Als bij een herstart een schrijfbewerking wordt herhaald, moet het ontwerp duplicaten voorkomen of herkennen dat het effect al bestaat. Een externe integratie die geen annulering ondersteunt, kan een verzoek hebben geaccepteerd, ook al is de client gestopt met wachten; de status moet die onzekerheid weergeven en niet aannemen dat er geen effect is opgetreden.
Als veilig doorgaan vanaf het laatst opgeslagen punt niet mogelijk is, markeer de taak dan voor beoordeling of voor specifiek herstel. Automatisch hervatten vanaf een onnauwkeurig vastgelegd punt kan een onjuist resultaat opleveren. Documenteer welke fasen herhaalbaar zijn, welke verificatie vereisen en onder welke voorwaarden het proces als voltooid mag worden beschouwd.
Test de limieten en onderbrekingen
Tests moeten zowel het stoppen als de eindstatus controleren, niet alleen of er een exception is opgetreden. Gebruik beheersbare afhankelijkheden om een trage aanroep, een query die de toegestane tijd overschrijdt en een antwoord dat precies op de deadline binnenkomt te simuleren. Controleer of een fase niet voorbij de globale deadline kan doorgaan.
Test een annulering tussen fasen en tijdens een bewerking die alleen kan stoppen wanneer deze terugkeert. Simuleer ook een abrupte beëindiging op relevante momenten: na een extern effect, vóór het opslaan van de status en tijdens het opruimen. Controleer na het herstarten van de worker of de status begrijpelijk is en of het hervattingsbeleid geen werk dupliceert of overslaat. Gebruik voor deze tests geïsoleerde gegevens en maak ze niet afhankelijk van echte externe services.
Checklist voor een bestaand proces

- Breng de limieten van PHP, de server, de worker en elke gebruikte client in kaart.
- Stel een globale deadline en tijdslimieten per fase vast die elk binnen die deadline blijven.
- Geef waar mogelijk de resterende tijd door aan HTTP, de database en andere processen.
- Controleer op veilige punten op annulering en start na ontvangst ervan geen nieuw werk.
- Leg verschillende statussen, de huidige fase en de oorzaak van de beëindiging vast.
- Beschrijf welke gedeeltelijke effecten kunnen achterblijven en onder welke voorwaarden hervatten mogelijk is.
- Test vertragingen, annuleringen, abrupte beëindigingen en de status na een herstart.
Een degelijk ontwerp belooft niet dat elke bewerking onmiddellijk kan worden gestopt. Het maakt de beschikbare tijd expliciet, beperkt het wachten op elke afhankelijkheid en bewaart voldoende informatie om een onderbreking te kunnen interpreteren. Door die combinatie wordt een langlopend proces geen ondoorzichtige uitvoering meer, maar een beheersbare en verifieerbare werkeenheid.



