v13.36.0, en verbinden we de basisregistratiemethoden van de service container met het langetermijnonderhoud van packages. Alleen scoped() kiezen betekent niet dat alle verwijzingen tussen objecten en alle statische state worden gereset.
Kies de registratiemethode op basis van de levensduur van de service
Deze tabel vergelijkt normale resoluties. Controleer speciale paden, zoals resolutie met expliciete parameters of contextual binding, apart.
Ook bij
bind() blijft de verwijzing bestaan als je de opgehaalde service opslaat in een property van een andere singleton. De registratiemethode is een regel van de container voor het aanmaken en hergebruiken, geen regel die objecten die de gebruiker vasthoudt geforceerd opnieuw aanmaakt.
scoped combineert gedeelde registratie met het bijhouden van te verwijderen sleutels
De onderzochteContainer::scoped() doet de volgende twee dingen:
- De registratiesleutel vastleggen in
scopedInstances. singleton()aanroepen en registreren als gedeelde binding.
instances. forgetScopedInstances() voert unset() uit op de opgeslagen instanties voor de vastgelegde sleutels. Omdat de aanmaaklogica van de binding blijft bestaan, kan bij de volgende normale resolutie een nieuw object worden aangemaakt.
Dit proces initialiseert geen properties van het oude object en herschrijft geen verwijzingen die andere objecten vasthouden. Een oud object waarnaar nog een verwijzing bestaat, kan nog steeds worden gebruikt.
De uitvoeringsomgeving maakt de grens
De container zelf houdt niet in de gaten wanneer een HTTP-request of job begint.- Queue worker:
QueueServiceProvidergeeft een callback die de scope reset door aan de Worker.Worker::daemon()roept deze aan in de lus voordat de volgende job wordt opgehaald, en binnen de callback worden onder andereforgetScopedInstances()en het wissen van de geresolvede instanties van Facades uitgevoerd. - Octane: De officiële standaardconfiguratie registreert
FlushTemporaryContainerInstancesbijOperationTerminated. Deze listener roeptforgetScopedInstances()aan. - Eigen langlopende commando’s of lussen: Simpelweg herhaaldelijk
make()aanroepen vormt geen grens. De levenscyclus moet aan de kant van het uitvoeringsplatform worden ontworpen.
Maak state die binnen een verwerking wordt gedeeld scoped
Neem als voorbeeld een bezorgpackage dat binnen één request of job de identifier van de bestemming wil delen. In plaats van de HTTP-Request direct vast te houden, slaan we alleen de benodigde waarde op.handle() van een job in de gebruikende applicatie stel je de identifier in nadat de invoer is gevalideerd en de rechten zijn gecontroleerd. Andere services die dit type binnen dezelfde levenscyclus resolven, zien dezelfde context.
scoped() geen persistentie naar een database of externe cache. Waarden die aan de volgende job moeten worden doorgegeven, geef je expliciet mee als jobdata.
In Octane worden
register() en boot() van service providers uitgevoerd bij de initiële start van de worker. Ontwerp niet zo dat de huidige gebruiker of bestemming in boot() in de context wordt opgeslagen. Stel waarden per verwerking pas in nadat de verwerking is begonnen.Verwijzingen van een singleton naar scoped worden niet automatisch bijgewerkt
Bij de volgende registratie werkt het niet zoals bedoeld als je alleen de context scoped maakt.DeliveryService de context in de constructor in een property opslaat, blijft hij de eerst aangemaakte context vasthouden. Ook als de opgeslagen context uit de container wordt verwijderd, veranderen de properties van de al aangemaakte DeliveryService niet.
Kies een oplossing die past bij de verantwoordelijkheid van de service.
- Geef de per verwerking benodigde waarden mee als methodeargumenten. Als er geen state gedeeld hoeft te worden, is dit het eenvoudigst.
- Maak ook de vasthoudende kant scoped. Zowel
DeliveryServiceals de context worden per verwerking opnieuw aangemaakt. - Geef een resolver mee die bij gebruik resolvet. Als de singleton behouden moet blijven, haal je de benodigde service telkens op uit de huidige container.
DeliveryService in dit voorbeeld moet worden aangepast zodat hij in de constructor een Closure ontvangt en een API wordt die deze bij elke bewerking aanroept. Als je de resolver in de constructor maar één keer aanroept en het resultaat opslaat, is het probleem niet opgelost. Dit is een ontwerpvoorbeeld waarbij de container resolver uit de officiële Octane-documentatie wordt toegepast op een packagespecifieke context.
Controleer ook state die scoped niet wist
scoped() verwijdert de volgende state niet automatisch:
- Waarden die zijn toegevoegd aan eigen statische properties van het package
- Verwijzingen naar de context die zijn opgeslagen in een andere singleton of in globale variabelen
- Een “huidige gebruiker” of “huidige bestemming” die in een singleton wordt vastgehouden
- Verwijzingen die worden vastgehouden door eigen Facades of cachelagen
Schrijf tests die grenzen overschrijden binnen dezelfde container
Als HTTP-tests alleen elke keer een nieuwe applicatie aanmaken, kun je problemen missen waarbij een langlopend proces dezelfde container blijft gebruiken. Controleer eerst op containerniveau het delen binnen dezelfde verwerking en het opnieuw aanmaken na de grens. De volgende tests zijn in PHPUnit-formaat. De eerste test gebruikt, net als de officiële Container-tests,forgetScopedInstances() en controleert het effect van de grens zonder de hele Worker te starten.
Unittests op containerniveau verifiëren niet het werkelijke uitvoeringspad van de Octane-sandbox of de queue worker. Je hebt ook integratietests nodig die opeenvolgende verwerkingen uitvoeren in de uitvoeringsomgevingen waarvoor je ondersteuning claimt. Bij deploys die de registratiemethode of de service-implementatie wijzigen, herlaad je de langlopende processen om de nieuwe code toe te passen.
Gerelateerde pagina’s
Hooks na het resolven van packageservices
Bekijk afterResolving, het ophalen van gedeelde instanties en de verschillen in configuratie bij herhaalde resolutie.
Laravel Octane
Bekijk aandachtspunten voor het vasthouden van de Request en de container, en voor het beheer van langlopende processen.
Geraadpleegde primaire bronnen
- Officiële Laravel-documentatie: Binding scoped singletons
- Officiële Laravel-documentatie: Dependency injection and Octane
- Container: scoped(), singleton(), forgetScopedInstances() en resolve()
- ContainerTest: delen en opnieuw aanmaken met scoped
- QueueServiceProvider: resetScope die aan de Worker wordt doorgegeven
- Worker: scope resetten in daemon()
- Octane: FlushTemporaryContainerInstances
- Octane: standaardlisteners van OperationTerminated