I den här artikeln kommer vi att utforska de olika sätten att implementera pipeline-designmönstret från grunderna till mer komplexa lösningar.
Pipeline-mönstret
Pipeline-mönstret är ett mjukvaru-designmönster som ger möjlighet att bygga och utföra en sekvens av operationer.
Det här mönstret används bättre tillsammans med plugin-mönstret, för att dynamiskt bygga pipelinen när applikationen startar.
Sequence
Den mest grundläggande implementeringen av en pipeline skulle vara en enkel sekvens av operationer.
Gränssnittet för en operation kan åberopas för att bearbeta data.
Pipelinen bearbetar varje operation en efter en. Pipelineklassen implementerar också gränssnittet IOperation så att de kan kombineras.
Operationen kan skrivas i en dedikerad klass.
Och använda en wrapper för att automatiskt skapa en operation från en lambda.
Pipelineoperationerna bör registreras innan pipelinen anropas.
Cirkelbrytare
Den första funktionen som du vill lägga till i din pipeline är att lägga till en kretsbrytare.
Varje operation kommer att returnera resultatet : fail eller success.
Om en operation misslyckas ska pipelineutförandet stoppas.
Asynkron
Ett annat krav kan vara att ha en pipeline som kan hantera asynkrona operationer.
Varje operation måste nu anropa nästa operation i pipelinen, när de är färdiga med att behandla data.
Pipelinen är lite mer komplicerad, eftersom den måste ställa in nästa operation när en ny operation registreras. En annan lösning är att använda en builder.
Denna operation är asynkron och kommer att köras i en dedikerad tråd, när tiden är ute kommer den att åberopa nästa operation för att fortsätta pipelinen.
Den generiska operationen kan användas både med en enkel åtgärd, eller använda en inbyggd brytare om du använder en funktion.
Detta enkla exempel använder flera av de funktioner vi implementerade.
Nu vet du hur du gör din pipeline asynkron !
Det skulle vara ännu bättre om du hade en annan callback till den föregående operationen så att du kunde få resultatet att gå motströms genom pipelinen.
Plugin
Den främsta anledningen till att använda pipeline-designmönstret är ofta kravet på att kunna lägga till plugins som antingen lägger till operationer till en befintlig pipeline eller att koppla en operation mitt i den.
Pipelinen är egentligen grundläggande, men den här gången är operationerna exponerade.
Låt oss ta en enkel applikation med en pipeline som bara visar de tre stegen i konsolen. Det här programmet har också stöd för plugins för att ändra pipelinen.
Det första pluginet kommer att koppla in en annan operation i det andra facket i pipelinen.
Det andra pluginet kommer att lägga till en ny operation i slutet av pipelinen.
Applicationen och insticksprogrammen är sammanställda, vi kan åberopa pipelinen.
Batch
En annan användbar funktion är att kunna bearbeta batchaffärer i samma pipeline än enskilda objekt.
Batchpipelinen omsluter en pipeline och anropar varje operation på varje objekt.
Varje objekt omslutas, så att vi kan komma ihåg resultatet av kretsbrytaren.
Denna operation kontrollerar om heltalet har den erforderliga storleksordningen.
Pipelinen ska kontrollera storleksordningen för en sats av heltal.
Pipelinen anropar endast nästa operation för objekt som inte misslyckades.
Högpresterande pipeline
Pipeline designmönstret kan också avse en mycket mer specifik och prestandainriktad mjukvaruarkitektur.
Vissa projekt använder en pipeline för att optimera bearbetningen av en stor mängd data genom att köra varje operation i pipelinen i en särskild tråd.
Varje tråd kommer att konsumera och producera data från en samtidig kö som kommer att fungera som buffert.
Den här gången kommer vi att använda asynkrona operationer med en kretsbrytare.
Om operationen är framgångsrik ska den anropa nästa, eller avslutas om den misslyckats.
Pipelinen är utformad för att kringgå kretsbrytaren. Oavsett om den lyckas eller misslyckas kommer den alltid att fortsätta den överordnade pipeline-sekvensen och anropa nästa operation.
Scenariot är lite komplext, så jag kommer inte att förklara allt. Tanken är att ha olika trådar för att behandla inkommande order. När en order är färdigbehandlad kontrollerar vi orderns status.
Varje orderbehandlare är isolerad i en dedikerad tråd, så att du kan optimera hur du lagrar data och har direkt tillgång till minnet utan att använda lås.
Betalningsorderbehandlaren är den enda tråden som kan komma åt användarsaldon. Den kan hämta eller uppdatera alla saldon utan att bekymra sig om samtidighetsproblem.
Pipelinen bearbetar sekvensen av operationer så snabbt som möjligt.
Slutsats
Pipeline Design Pattern har många mycket olika sätt att implementeras, från en enkel Chain of Command till ett mer komplext Workflow.
Många funktioner kan behövas, såsom circuit-breaker, asynkron eller buffert, men för det mesta vill man använda pipelines när man vill ha plugins som kan haka på pipeline exekveringsflödet.