Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Al ejecutar un flujo de trabajo en .NET, el modo de ejecución controla cómo se procesan los superpasos y cómo se entregan los eventos al consumidor. La InProcessExecution clase expone dos modos de ejecución: OffThread y Lockstep.
Overview
| OffThread (valor predeterminado) | Lockstep | |
|---|---|---|
| Ejecución de superstep | Subproceso en segundo plano | Hilo del consumidor |
| Entrega de eventos | Inmediato, a medida que se generan eventos | Se procesa por lotes después de completar cada superpaso. |
| Ejecución de un paso | Independiente de la gestión de eventos | Pausado hasta que se consuman eventos por lotes |
| Concurrencia | El consumidor lee eventos mientras se ejecutan superpasos | Ejecución alterna de consumidor y superpaso |
| Ideal para | Streaming en tiempo real, escenarios de producción | Pruebas, depuración, ordenación determinista |
OffThread
OffThread es el modo de ejecución predeterminado . Los superpasos se ejecutan en un subproceso en segundo plano y los eventos se transmiten inmediatamente a medida que se generan a través de una implementación basada en canal.
// 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);
Cómo funciona
- Una tarea en segundo plano se ejecuta de forma continua mientras los mensajes están pendientes.
- A medida que los ejecutores producen salidas o eventos, los objetos resultantes
WorkflowEventse escriben en un sin límitesChannel<WorkflowEvent>. - El consumidor lee los eventos del canal a través de
WatchStreamAsync, recibiéndolos en tiempo real a medida que se producen. - Cuando todos los superpasos están completos y no quedan mensajes, la ejecución se detiene en un estado
o .
Dado que el bucle superstep y el consumidor se ejecutan simultáneamente, los eventos aparecen en cuanto se generan, no hay ninguna latencia de búfer. Esto hace que OffThread sea ideal para escenarios de streaming en los que importa la entrega de eventos de baja latencia, como mostrar actualizaciones de token por token en una interfaz de usuario.
Ejecuciones simultáneas
OffThread también admite una variante simultánea que permite que varias ejecuciones compartan simultáneamente la misma instancia de flujo de trabajo:
await using StreamingRun run = await InProcessExecution.Concurrent.RunStreamingAsync(workflow, input);
Importante
La ejecución simultánea requiere que todos los ejecutores del flujo de trabajo se declaren crossRunShareable (en el constructor) o que se proporcionen como métodos de fábrica.
Lockstep
En el modo Lockstep, los superpasos se ejecutan en el subproceso del consumidor en lugar de en una tarea en segundo plano. Los eventos se acumulan durante cada superpaso y se emiten como un lote después de que se complete el superpaso.
await using StreamingRun run = await InProcessExecution.Lockstep.RunStreamingAsync(workflow, input);
Cómo funciona
- El consumidor llama a
WatchStreamAsync, que controla el bucle de ejecución. - Un superpaso se ejecuta hasta la finalización y los eventos se acumulan en una cola.
- Una vez finalizado el superpaso, todos los eventos en cola se devuelven al consumidor.
- El siguiente superpaso comienza solo después de que el consumidor haya recibido todos los eventos del anterior.
Este patrón de alternancia significa que el consumidor y el motor de flujo de trabajo nunca se ejecutan simultáneamente. La entrega de eventos es determinista: se garantiza que todos los eventos de un superstep lleguen antes de cualquier evento del siguiente superstep.
Cuándo usar Lockstep
Lockstep es útil cuando:
- Pruebas : el orden de eventos determinista facilita las aserciones.
- Depuración : la depuración paso a paso es más fácil cuando la ejecución permanece en el subproceso del consumidor.
- Procesamiento ordenado : escenarios en los que necesita procesar completamente los eventos de un superstep antes de que comience el siguiente superpaso.
Elección de un modo de ejecución
Para la mayoría de los escenarios de producción, se recomienda el modo OffThread predeterminado. Proporciona la mejor capacidad de respuesta y permite que el flujo de trabajo continúe procesando mientras el consumidor controla los eventos.
Use Lockstep cuando el comportamiento determinista sea más importante que el rendimiento, como en pruebas unitarias o sesiones de depuración.
// 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);
Ejecución sin streaming
Ambos modos de ejecución admiten la ejecución sin streaming a través de RunAsync. En modo de no streaming, el flujo de trabajo se ejecuta hasta la finalización y recopila todos los eventos en un Run objeto en lugar de transmitirlos de forma incremental:
Run run = await InProcessExecution.RunAsync(workflow, input);
// Access all emitted events
foreach (WorkflowEvent evt in run.OutgoingEvents)
{
// Process events
}
Dado que la ejecución sin streaming recopila todos los eventos después de la finalización, no se aplica la ventaja de entrega de eventos en tiempo real de OffThread. La principal diferencia entre los modos en escenarios que no son de streaming es la gestión de hilos: OffThread ejecuta supersteps en un hilo en segundo plano, liberando el hilo que realiza la llamada mientras espera la finalización, mientras que Lockstep ejecuta supersteps en el hilo del autor de la llamada, bloqueándolo hasta que se completa el flujo de trabajo.
La ejecución sin streaming usa el modo OffThread predeterminado. Para usar Lockstep con ejecución sin streaming:
Run run = await InProcessExecution.Lockstep.RunAsync(workflow, input);
Pasos siguientes
Los modos de ejecución no son aplicables a los flujos de trabajo de Python. Los flujos de trabajo de Python usan un único modelo de ejecución que controla el procesamiento de superstep y la entrega de eventos a través de un generador asincrónico. Este modelo es similar al modo Lockstep de .NET: los pasos no avanzan a menos que el consumidor extraiga activamente eventos del generador.
Para obtener información sobre cómo ejecutar flujos de trabajo de Python, consulte Generador de flujos de trabajo y ejecución.
Al ejecutar un flujo de trabajo en Go, el entorno de ejecución controla cómo se procesan los supersteps y cómo se entregan los eventos al consumidor. El workflow/inproc paquete expone tres entornos: Default/OffThread, Lockstepy .Concurrent
Overview
| OffThread/Default | Lockstep | Concurrent | |
|---|---|---|---|
| Ejecución de superstep | Goroutine en segundo plano | Impulsado por el consumidor de eventos | Goroutine en segundo plano |
| Entrega de eventos | Inmediato, a medida que se generan eventos | En lotes a medida que se consume el flujo | Inmediato, a medida que se generan eventos |
| Ideal para | Streaming en tiempo real, escenarios de producción | Pruebas, depuración, ordenación determinista | Instancias de flujo de trabajo compartidas con enlaces seguros simultáneos |
OffThread
OffThread es el modo de ejecución predeterminado. Son equivalentes:
stream, err := inproc.Default.RunStreaming(ctx, wf, input)
stream, err := inproc.OffThread.RunStreaming(ctx, wf, input)
Cómo funciona
- Una goroutine en segundo plano ejecuta superpasos mientras haya mensajes pendientes.
- A medida que los ejecutores generan resultados o eventos, los eventos del flujo de trabajo se escriben en el flujo.
- El consumidor lee los eventos con
WatchStreamy los recibe a medida que se producen. - Cuando se completan todos los superpasos y no quedan mensajes, la ejecución se detiene con un estado inactivo o de solicitud pendiente.
Ejecuciones simultáneas
Use inproc.Concurrent cuando todos los enlaces del ejecutor del flujo de trabajo admitan la ejecución compartida simultánea:
stream, err := inproc.Concurrent.RunStreaming(ctx, wf, input)
if err != nil {
return err
}
defer stream.Close(ctx)
Lockstep
En el modo «Lockstep», la ejecución del flujo de trabajo avanza a medida que el consumidor lee del flujo. Esto hace que el orden de eventos sea determinista para las pruebas y la depuración.
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
}
Cómo funciona
- El consumidor llama a
WatchStream, que controla el bucle de ejecución. - Un superpaso se ejecuta hasta completarse y los eventos se acumulan.
- Los eventos acumulados se devuelven al consumidor.
- El siguiente superpaso comienza solo después de que el consumidor reciba los eventos del superpaso anterior.
Cuándo usar Lockstep
Utilice Lockstep cuando el comportamiento determinista importe más que la transmisión de baja latencia, como en pruebas unitarias, depuración o escenarios en los que quiera procesar por completo los eventos de un superpaso antes de que comience el siguiente superpaso.
Elección de un modo de ejecución
Para la mayoría de los escenarios de producción, use inproc.Default o inproc.OffThread. Se usa inproc.Lockstep cuando el orden de eventos determinista es más importante que la latencia de streaming, como en las pruebas. Use inproc.Concurrent solo cuando cada enlace del flujo de trabajo admita la ejecución compartida simultánea.
// 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)
Ejecución sin streaming
Todos los entornos de ejecución también admiten la ejecución sin transmisión Run, la cual se ejecuta hasta la siguiente pausa y almacena los eventos emitidos en la ejecución devuelta.
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)
}
}