Arbetsflödeskörningslägen

När du kör ett arbetsflöde i .NET styr körningsläget hur supersteg bearbetas och hur händelser levereras till konsumenten. Klassen InProcessExecution exponerar två körningslägen: OffThread och Lockstep.

Overview

OffThread (Förvald) Låssteg
Superstegskörning Bakgrundstråd Konsumentens diskussionstråd
Händelselämning Omedelbart, eftersom händelser utlöses Sammanställd efter att varje supersteg har slutförts
Stegexekvering Oberoende av händelsebearbetning Pausad tills batchhändelser förbrukas
Konkurrens Konsumenten läser händelser medan superstegsprocesser körs Växling mellan körning av konsument och supersteg
Bäst för Realtidsströmning, scenarier för produktion Testa, felsöka, deterministisk ordning

OffThread

OffThread är standardläge för exekvering. Supersteps körs i en bakgrundstråd och händelser strömmas genast så snart de genereras via en kanalbaserad lösning.

// OffThread is the default — these are equivalent:
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, input);
await using StreamingRun run = await InProcessExecution.OffThread.RunStreamingAsync(workflow, input);

Så här fungerar det

  1. En bakgrundsaktivitet kör supersteg kontinuerligt medan meddelanden väntar.
  2. Eftersom exekutorer ger utdata eller händelser skrivs de resulterande WorkflowEvent objekten till en obundna Channel<WorkflowEvent>.
  3. Konsumenten läser händelser från kanalen via WatchStreamAsyncoch tar emot dem i realtid när de produceras.
  4. När alla supersteg är slutförda och inga meddelanden finns kvar stoppas körningen med en Idle eller PendingRequests status.

Eftersom superstegsloopen och konsumenten körs parallellt visas händelser så snart de utlöses — det finns ingen buffertfördröjning. Detta gör OffThread perfekt för strömningsscenarier där händelseleverans med låg fördröjning är viktig, till exempel att visa uppdateringar för token per token i ett användargränssnitt.

Samtidiga körningar

OffThread stöder också en samtidig variant som gör att flera körningar kan dela samma arbetsflödesinstans samtidigt:

await using StreamingRun run = await InProcessExecution.Concurrent.RunStreamingAsync(workflow, input);

Important

Samtidig körning kräver att alla utförare i arbetsflödet deklareras crossRunShareable (på konstruktorn) eller anges som fabriksmetoder.

Låssteg

I Lockstep-läge körs supersteg i konsumentens tråd i stället för på en bakgrundsuppgift. Händelser ackumuleras under varje supersteg och genereras som en batch när supersteget har slutförts.

await using StreamingRun run = await InProcessExecution.Lockstep.RunStreamingAsync(workflow, input);

Så här fungerar det

  1. Konsumenten anropar WatchStreamAsync, som driver körningsloopen.
  2. Ett supersteg körs till slutförande och händelser ackumuleras i en kö.
  3. När supersteget är klart överlämnas alla köade händelser till konsumenten.
  4. Nästa supersteg börjar först när konsumenten har tagit emot alla händelser från föregående.

Det här alternerande mönstret innebär att konsumenten och arbetsflödesmotorn aldrig körs samtidigt. Händelseleveransen är deterministisk – alla händelser från ett supersteg kommer garanterat att komma före händelser från nästa supersteg.

När du ska använda Lockstep

Lockstep är användbart när:

  • Testning – deterministisk händelseordning gör försäkran enkla.
  • Felsökning – steg-för-steg-felsökning är enklare när körningen sker i konsumentens tråd.
  • Ordnad bearbetning – scenarier där du behöver bearbeta en superstegs händelser helt innan nästa supersteg börjar.

Välja körningsläge

För de flesta produktionsscenarier rekommenderas standardläget OffThread . Det ger bästa svarstid och gör att arbetsflödet kan fortsätta bearbeta medan konsumenten hanterar händelser.

Använd Lockstep när deterministiskt beteende är viktigare än prestanda, till exempel i enhetstester eller felsökningssessioner.

// Production: OffThread (default)
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, input);

// Testing: Lockstep for deterministic behavior
await using StreamingRun run = await InProcessExecution.Lockstep.RunStreamingAsync(workflow, input);

Körning utan direktuppspelning

Båda körningslägena stöder ickeströmmande körning via RunAsync. I icke-direktuppspelningsläge körs arbetsflödet till slutförande och samlar in alla händelser i ett Run objekt i stället för att strömma dem stegvis:

Run run = await InProcessExecution.RunAsync(workflow, input);

// Access all emitted events
foreach (WorkflowEvent evt in run.OutgoingEvents)
{
    // Process events
}

Eftersom icke-strömmande körning samlar in alla händelser efter slutförandet, gäller inte fördelen med händelseleverans i realtid för OffThread. Den primära skillnaden mellan lägen i icke-strömningsscenarier är trådning: OffThread kör supersteg på en bakgrundstråd, frigör den anropande tråden i väntan på slutförande, medan Lockstep kör supersteg på anroparens tråd och blockerar den tills arbetsflödet har slutförts.

Körning utan streaming använder standardläget "OffThread". Så här använder du Lockstep med körning utan direktuppspelning:

Run run = await InProcessExecution.Lockstep.RunAsync(workflow, input);

Nästa steg

Körningslägen gäller inte för Python-arbetsflöden. Python-arbetsflöden använder en enda körningsmodell som hanterar superstegsbearbetning och händelseleverans via en asynkron generator. Den här modellen liknar .NET Lockstep-läget – steg går inte framåt om inte konsumenten aktivt hämtar händelser från generatorn.

Information om hur du kör Python-arbetsflöden finns i Workflow Builder &execution .

När du kör ett arbetsflöde i Go styr körningsmiljön hur supersteg bearbetas och hur händelser levereras till konsumenten. Paketet workflow/inproc exponerar tre miljöer: Default/OffThread, Lockstepoch .Concurrent

Overview

OffThread / Standard Låssteg Samtidig
Superstegskörning Bakgrundsgorutin Drivs av eventkonsumenten Bakgrundsgorutin
Händelselämning Omedelbart, eftersom händelser utlöses Batchvis när strömmen konsumeras Omedelbart, eftersom händelser utlöses
Bäst för Realtidsströmning, scenarier för produktion Testa, felsöka, deterministisk ordning Delade arbetsflödesinstanser med samtidiga säkra bindningar

OffThread

OffThread är standardkörningsläget. Dessa är likvärdiga:

stream, err := inproc.Default.RunStreaming(ctx, wf, input)
stream, err := inproc.OffThread.RunStreaming(ctx, wf, input)

Så här fungerar det

  1. En goroutin i bakgrunden kör supersteg medan meddelanden väntar.
  2. När utförare ger utdata eller händelser skrivs arbetsflödeshändelser till strömmen.
  3. Konsumenten läser händelser med WatchStream och tar emot dem i takt med att de genereras.
  4. När alla supersteg är slutförda och inga meddelanden finns kvar stoppas körningen med statusen inaktiv eller väntande begäran.

Samtidiga körningar

Använd inproc.Concurrent när alla exekverarbindningar i arbetsflödet stöder delad samtidig körning:

stream, err := inproc.Concurrent.RunStreaming(ctx, wf, input)
if err != nil {
    return err
}
defer stream.Close(ctx)

Låssteg

I Lockstep-läge avancerar arbetsflödeskörningen när konsumenten läser från dataströmmen. Detta gör händelseordningen deterministisk för tester och felsökning.

stream, err := inproc.Lockstep.RunStreaming(ctx, wf, input)
if err != nil {
    return err
}
defer stream.Close(ctx)

for evt, err := range stream.WatchStream(ctx) {
    if err != nil {
        return err
    }
    // inspect event
}

Så här fungerar det

  1. Konsumenten anropar WatchStream, som driver körningsloopen.
  2. Ett supersteg körs till slutförande och händelser ackumuleras.
  3. De ackumulerade händelserna ges till konsumenten.
  4. Nästa supersteg börjar först efter att konsumenten har fått det tidigare superstegets händelser.

När du ska använda Lockstep

Använd Lockstep när deterministiskt beteende är viktigare än strömning med låg latens, till exempel enhetstester, felsökning eller scenarier där du vill bearbeta händelser i en supersteg innan nästa supersteg börjar.

Välja körningsläge

I de flesta produktionsscenarier använder du inproc.Default eller inproc.OffThread. Använd inproc.Lockstep när deterministisk händelseordning är viktigare än svarstid för direktuppspelning, till exempel i tester. Använd inproc.Concurrent endast när varje bindning i arbetsflödet stöder samtidig delad körning.

// Production: OffThread (default)
stream, err := inproc.Default.RunStreaming(ctx, wf, input)
if err != nil {
    return err
}
defer stream.Close(ctx)

// Testing: Lockstep for deterministic behavior
testStream, err := inproc.Lockstep.RunStreaming(ctx, wf, input)
if err != nil {
    return err
}
defer testStream.Close(ctx)

Körning utan direktuppspelning

Alla körningsmiljöer stöder även icke-strömmande Run, som kör fram till nästa avbrott och lagrar genererade händelser i den returnerade körningen.

run, err := inproc.Default.Run(ctx, wf, input)
if err != nil {
    return err
}

for evt := range run.NewEvents() {
    if output, ok := evt.(workflow.OutputEvent); ok {
        fmt.Printf("Final result: %v\n", output.Output)
    }
}

Nästa steg