Ga direct naar de inhoud
DedicatedPHP Contact

Wanneer een PHP-proces halverwege strandt: compensaties ontwerpen

Leer hoe je PHP-workflows herstelt die tussen systemen vastlopen: wanneer je opnieuw probeert, wanneer je compenseert en hoe je resultaten registreert en uitzonderingen escaleert.

Redactioneel diagram van een PHP-proces met stappen tussen een lokale database en een externe API, inclusief retries en compensaties

Een bedrijfsproces kan een deel van zijn werk voltooien en vastlopen voordat het klaar is. Een PHP-applicatie maakt bijvoorbeeld een account aan in de eigen database, maar slaagt er niet in dit account bij een externe dienst in te richten. De workflow zomaar opnieuw uitvoeren kan dan dubbele effecten veroorzaken; het proces als mislukt beschouwen kan systemen inconsistent achterlaten. Compensaties in gedistribueerde PHP-processen maken het mogelijk vast te leggen hoe je op zulke gedeeltelijke resultaten reageert, zonder ervan uit te gaan dat meerdere systemen deelnemen aan één atomaire transactie.

De belangrijkste beslissing is niet alleen hoe je ongedaan maakt wat er is gebeurd. Sommige effecten zijn niet exact terug te draaien, en ook een compensatie kan mislukken. Het ontwerp moet de werkelijke status van de bewerking zichtbaar maken, herstel mogelijk maken en aangeven wanneer menselijke tussenkomst nodig is.

Lokale transacties, retries en compensaties lossen verschillende problemen op

Lokale transacties, retries en compensaties lossen verschillende problemen op — guía visual de DedicatedPHP

Een databasetransactie beschermt wijzigingen binnen de grenzen van die database. Als het proces meerdere rijen opslaat en een bewerking mislukt voordat de COMMIT is uitgevoerd, kan het een ROLLBACK uitvoeren om die wijzigingen ongedaan te maken. Die rollback trekt echter geen verzonden e-mail in, annuleert niet automatisch een verzoek dat al door een API is geaccepteerd en draait geen wijzigingen terug die in een andere database zijn bevestigd.

Een retry voert een bewerking opnieuw uit die mogelijk is mislukt door een tijdelijk probleem, zoals een timeout of een storing. Dit is alleen geschikt als de gevolgen van herhaling bekend zijn. Het verzoek kan het externe systeem hebben bereikt terwijl het antwoord verloren ging; zonder idempotency key of statuscontrole kan een retry een duplicaat aanmaken.

Een compensatie voert een bedrijfsactie uit die een al voltooide stap tegenwerkt, bijvoorbeeld toegang uitschakelen die zojuist is aangemaakt. Dit is geen technische rollback en garandeert niet dat de exacte eerdere status wordt hersteld. Een reconciliatie vergelijkt daarentegen wat lokaal is vastgelegd met de status van de betrokken systemen en helpt verschillen op te sporen en op te lossen. Dit kan nodig zijn, ook als retries en compensaties beschikbaar zijn.

Modelleer elke bewerking als een reeks waarneembare stappen

Beschrijf de workflow als afzonderlijke stappen voordat je exception handlers schrijft. Geef voor elke stap aan welk systeem wordt gewijzigd, welk resultaat als succes geldt, hoe de bewerking wordt geïdentificeerd, of herhalen veilig is en welk alternatief er is als de stap niet kan worden voltooid. Bepaal ook welke effecten consistent moeten blijven; die bedrijfsregel is de invariant die het herstel richting geeft.

Sla in de applicatie een registratie van de bewerking en de stappen op. Een eenvoudig model kan een stabiele bewerkings-ID, de algemene status, de stapnaam, het resultaat, het aantal pogingen, tijdstempels en de laatste relevante fout bevatten. Statussen zoals in afwachting, bezig, voltooid, mislukt, bezig met compenseren en beoordeling vereist helpen onderscheid te maken tussen wat bekend is en wat nog niet is bevestigd.

Sla de lokale wijziging en de werkregistratie atomair op wanneer ze gekoppeld moeten blijven. Een job queue kan de externe aanroep later verwerken; het outbox-patroon is een optie om te voorkomen dat de databasewijziging wordt bevestigd terwijl de melding die de volgende stap moest starten verloren gaat. Dit voorkomt geen netwerkstoringen: de consumer moet nog steeds dubbele berichten en onzekere resultaten aankunnen.

Houd geen databasetransactie open tijdens een netwerkaanroep. Externe aanroepen hebben latency en kunnen vastlopen, terwijl de langdurige transactie resources bezet houdt en de twee systemen niet atomair maakt. Bevestig lokaal werk volgens een expliciete volgorde en registreer wat nodig is om verder te gaan of te compenseren.

Ontwerp expliciete, begrensde en idempotente compensaties

Bepaal voor elke stap die een effect veroorzaakt of er een compensatie bestaat en wanneer die moet worden uitgevoerd. De compensatie hoeft niet de letterlijke inverse te zijn. Als een account al een melding heeft ontvangen, kun je het feit dat het bericht is gelezen niet ongedaan maken; mogelijk moet je een correctie registreren of de annulering melden. Als een actie onomkeerbaar is of juridische of financiële gevolgen heeft, is het wellicht juist om de workflow te stoppen en te escaleren.

  • Idempotentie: dezelfde compensatie twee keer uitvoeren mag geen extra effecten veroorzaken. Gebruik waar het systeem dit ondersteunt een stabiele bewerkings-ID of idempotency key en registreer het resultaat.
  • Volgorde: bepaal welke stappen worden gecompenseerd en in welke volgorde. Gewoonlijk probeer je stappen in omgekeerde volgorde van uitvoering terug te draaien, maar afhankelijkheden en bedrijfsregels kunnen een andere volgorde vereisen.
  • Grenzen: bepaal welke fouten retries toestaan, hoeveel pogingen je doet en wanneer je stopt. Wacht tussen pogingen en voorkom onbeperkte retries.
  • Onzekerheid: als een API-timeout optreedt, controleer dan de status of gebruik een idempotency key voordat je een aanmaakverzoek herhaalt of een mogelijk onjuiste compensatie uitvoert.

De compensatielogica moet een herkenbare bedrijfsbewerking zijn, geen generiek blok dat gegevens verwijdert zodra een willekeurige exception wordt opgevangen. Bewaar voldoende geschiedenis om uit te leggen wat er is gebeurd en te controleren of de reactie aan de productregels voldoet.

Hypothetisch voorbeeld: een account in twee systemen aanmaken

Stel dat een workflow een lokaal account aanmaakt en een externe provider verzoekt een werkruimte te activeren. De applicatie wijst een bewerkings-ID toe en registreert het aanmaken als in afwachting. In een lokale transactie slaat de applicatie het account en een job voor het verzoek tot inrichting op. Een PHP-worker verwerkt de job en registreert de externe ID en het resultaat van het verzoek.

Als de provider de activering bevestigt, markeert de workflow de bewerking als voltooid. Als de provider antwoordt met een bekende tijdelijke fout, kan de job met begrensde retries en dezelfde idempotency key opnieuw worden geprobeerd. Als het antwoord onzeker is, probeert de applicatie eerst vast te stellen of de werkruimte bestaat. Bevestigt de provider dat de werkruimte is aangemaakt, maar verhindert een latere lokale vereiste dat het aanmaken wordt voltooid, dan kan het systeem de deactivering als compensatie aanvragen en het resultaat opslaan.

Als de deactivering mislukt, mag je niet aangeven dat het aanmaken is teruggedraaid. De bewerking blijft zichtbaar met de status herstel nodig of beoordeling vereist, samen met de lokale en externe ID's, de pogingen en de fout. Het operationele team heeft een procedure nodig om de provider te controleren, de toegestane actie te bepalen en de uitkomst te registreren. Dit voorbeeld is hypothetisch: de concrete acties hangen af van de mogelijkheden van de API en de bedrijfsregels.

Wanneer ook de compensatie mislukt: inzicht en beoordeling

Een gedistribueerde workflow kan niet garanderen dat elke actie automatisch ongedaan wordt gemaakt. Ontwerp een expliciete uitweg voor uitgeputte retries, een onduidelijk extern antwoord of een mislukte compensatie. Behoud de status zonder de inconsistentie te verbergen en presenteer de bewerking niet als voltooid aan de gebruiker als dat nog niet zo is.

Geef support of operations een overzicht met de status per stap, de laatste fout, correlatie-ID's en toegestane acties. Menselijke beoordeling moet toegangscontroles hebben en een audittrail van de beslissing achterlaten. Maak metrics en alerts beschikbaar om vastgelopen bewerkingen, mislukte compensaties en verschillen die langer bestaan dan operationeel aanvaardbaar is op te sporen. Een periodieke reconciliatietaak kan lokale registraties vergelijken met het externe systeem en zaken aanmaken om verschillen op te lossen.

Test gedeeltelijke storingen en bepaal of compensatie nodig is

Test gedeeltelijke storingen en bepaal of compensatie nodig is — guía visual de DedicatedPHP

Tests moeten meer omvatten dan het succesvolle pad. Simuleer fouten vóór en na elk effect, late antwoorden, timeouts met een onbekende uitkomst, dubbele berichten, onderbroken processen en storingen tijdens compensatie. Controleer de opgeslagen status nadat je de worker opnieuw hebt gestart en bevestig dat retries geen accounts of andere bewerkingen dupliceren.

  • Blijven de bewerkings-ID en de resultaten van elke stap behouden?
  • Levert een herhaald bericht hetzelfde resultaat op zonder dubbele effecten?
  • Wordt de externe status gecontroleerd wanneer het antwoord op een verzoek onzeker is?
  • Wordt de compensatie in de verwachte volgorde uitgevoerd en is herhaling veilig?
  • Blijft een bewerking na een mislukte compensatie zichtbaar en wordt deze naar het beoordelingsproces gestuurd?
  • Kan de lokale status achteraf met het externe systeem worden gereconcilieerd?
  • Controleren de tests de bedrijfsinvarianten en niet alleen de responscodes?

Als de workflow gevolgen heeft voor slechts één systeem en een lokale transactie al zijn wijzigingen beschermt, kan die transactie met eenvoudig herstel volstaan. Als er herhaalbare externe effecten zijn met bekende garanties, zijn idempotente retries en reconciliatie mogelijk voldoende. Wanneer een bevestigde stap moet worden tegengewerkt om een bedrijfsregel te behouden, definieer dan een compensatie. De extra complexiteit is de moeite waard wanneer de kosten van onopgemerkte gedeeltelijke statussen hoger zijn dan die van het bijhouden van registraties, tests en operationele procedures.

Wil je deze ideeën toepassen op je project?Laten we uw PHP-platform bespreken.
Bekijk gerelateerde service