

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Descripción de una tarea en AWS Flow Framework for Java
<a name="details"></a>

**Topics**
+ [Tarea](#details.task)
+ [Orden de ejecución](#details.order)
+ [Ejecución del flujo de trabajo](#details.workflow)
+ [No determinismo](#details.non)

## Tarea
<a name="details.task"></a>

La primitiva subyacente que utiliza Java AWS Flow Framework para gestionar la ejecución del código asíncrono es la clase. `Task` Un objeto tipo `Task` representa trabajo que hay que realizar de manera asíncrona. Cuando llama a un método asíncrono, el marco de trabajo crea una `Task` para ejecutar el código en ese método y lo pone en una lista para su ejecución más adelante. De manera parecida, al invocar una `Activity`, se crea una `Task` para dicha actividad. La llamada al método regresa después de esto, devolviendo normalmente una `Promise<T>` como resultado futuro de la llamada.

La clase `Task` es pública y puede usarse directamente. Por ejemplo, podemos volver a escribir el ejemplo de Hello World para que use una `Task` en lugar de un método asíncrono.

```
@Override
public void startHelloWorld(){
       final Promise<String> greeting = client.getName();
        new Task(greeting) {
        @Override
        protected void doExecute() throws Throwable {
        	client.printGreeting("Hello " + greeting.get() +"!");
        }
    };
}
```

El marco de trabajo llama al método `doExecute()` cuando todas las `Promise`s que se han pasado al constructor de las `Task` están listas. Para obtener más información sobre la `Task` clase, consulte la documentación. AWS SDK para Java 

El marco de trabajo también incluye una clase llamada `Functor` que representa una `Task` que es también una `Promise<T>`. El objeto `Functor` está listo cuando se completa la `Task`. En el siguiente ejemplo, se crea un `Functor` para obtener el mensaje de saludo:

```
Promise<String> greeting = new Functor<String>() {
    @Override
    protected Promise<String> doExecute() throws Throwable {
        return client.getGreeting();
    }
};
client.printGreeting(greeting);
```

## Orden de ejecución
<a name="details.order"></a>

Las tareas se vuelven elegibles para la ejecución solo cuando todos los parámetros escritos `Promise<T>`, que se han pasado a la actividad o al método asíncrono correspondientes, están listos. Una `Task` que está lista para la ejecución se mueve de manera lógica a una cola lista. En otras palabras, se programa para la ejecución. Para ejecutar la tarea, la clase de proceso de trabajo invoca el código que se escribió en el cuerpo del método asíncrono o programa una tarea de actividad en Amazon Simple Workflow Service (AWS) en el caso de un método de actividad. 

A medida que las tareas ejecutan y producen resultados, hacen que otras tareas estén preparadas y la ejecución del programa continúa avanzando. La manera en que el marco de trabajo ejecuta tareas es importante para comprender el orden en el que se ejecuta su código asíncrono. El código que aparece secuencialmente en su programa podría no ejecutarse en ese orden.

```
Promise<String> name = getUserName();
printHelloName(name);
printHelloWorld();
System.out.println("Hello, Amazon!");

@Asynchronous
private Promise<String> getUserName(){
	return Promise.asPromise("Bob");
}
@Asynchronous
private void printHelloName(Promise<String> name){
	System.out.println("Hello, " + name.get() + "!");
}
@Asynchronous
private void printHelloWorld(){
	System.out.println("Hello, World!");
}
```

El código en la lista de arriba imprimirá lo siguiente:

```
Hello, Amazon!
Hello, World!
Hello, Bob
```

Quizás no sea lo que esperaba pero puede explicarse fácilmente analizando cómo se ejecutaron las tareas para los métodos asíncronos:

1. La llamada a `getUserName` crea una `Task`. La llamaremos `Task1`. Como `getUserName` no toma ningún parámetro, `Task1` se pone inmediatamente en la cola de preparación.

1. A continuación, la llamada a `printHelloName` crea una `Task` que tiene que esperar el resultado de `getUserName`. La llamaremos `Task2`. Como el valor requerido aún no está listo, `Task2` se coloca en la lista de espera.

1. A continuación se crea una tarea para` printHelloWorld` y se añade a la cola lista. La llamaremos `Task3`.

1. A continuación, la instrucción `println` imprime "Hello, Amazon\$1" en la consola.

1. En este punto, `Task1` y `Task3` están en la cola lista y `Task2` está en la lista de espera.

1. El proceso de trabajo ejecuta `Task1` y su resultado hace que `Task2` esté listo. `Task2` se añade a la cola lista por detrás de `Task3`.

1. `Task3` y `Task2` se ejecutan, a continuación, en ese orden.

La ejecución de actividades sigue el mismo patrón. Cuando se llama a un método en el cliente de actividad, este crea una `Task` que, cuando se ejecuta, programa una actividad en Amazon SWF.

El marco de trabajo confía en características como la generación de códigos y proxies dinámicos para inyectar la lógica para la conversión de llamadas de método en invocaciones de actividad y tareas asíncronas en su programa.

## Ejecución del flujo de trabajo
<a name="details.workflow"></a>

La clase de proceso de trabajo también administra la ejecución de la implementación de flujo de trabajo. Cuando se llama a un método en el cliente de flujo de trabajo, llama a Amazon SWF para crear una instancia de flujo de trabajo. Las tareas de Amazon SWF no deben confundirse con las tareas del marco de trabajo. Una tarea en Amazon SWF es una tarea de actividad o una tarea de decisión. La ejecución de las tareas de actividad es sencilla. La clase de proceso de trabajo de actividad recibe tareas de actividad de Amazon SWF, invoca el método de actividad apropiado de la implementación y devuelve el resultado a Amazon SWF.

La ejecución de las tareas de decisión requiere más pasos. El proceso de trabajo de flujo de trabajo recibe las tareas de decisión de Amazon SWF. Una tarea de decisión es en realidad una solicitud que pregunta a la lógica de flujo de trabajo qué debe hacer a continuación. La primera tarea de decisión se genera para una instancia de flujo de trabajo cuando se inicia a través del cliente de flujo de trabajo. Al recibir esta tarea de decisión, el marco de trabajo comienza a ejecutar el código en el método de flujo de trabajo anotado con `@Execute`. Este método ejecuta la lógica de coordinación que programa actividades. Cuando el estado de la instancia de flujo de trabajo cambia, por ejemplo, cuando se completa una actividad, se programan tareas de decisión adicionales. En este punto, la lógica de flujo de trabajo puede decidir actuar en función del resultado de la actividad; por ejemplo, podría decidir programar otra actividad.

El marco de trabajo oculta todos estos detalles al desarrollador traduciendo a la perfección tareas de decisión a la lógica del flujo de trabajo. Desde el punto de vista de un desarrollador, el código tiene el mismo aspecto que un programa normal. Internamente, el marco de trabajo lo asigna a llamadas a Amazon SWF y a tareas de decisión mediante el historial que mantiene Amazon SWF. Cuando llega una tarea de decisión, el marco de trabajo reproduce la ejecución del programa incorporando los resultados de las actividades completadas hasta el momento. Las actividades y métodos asíncronos que estaban esperando estos resultados se desbloquean y la ejecución del programa avanza.

En la siguiente tabla se muestra la ejecución del flujo de trabajo de procesamiento de imágenes de ejemplo y el historial correspondiente.


**La ejecución del flujo de trabajo de miniaturas**  

| La ejecución del programa de flujo de trabajo | El historial que mantiene Amazon SWF  | 
| --- | --- | 
| Ejecución inicial | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/es_es/amazonswf/latest/awsflowguide/details.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/es_es/amazonswf/latest/awsflowguide/details.html)  | 
| Reproducción | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/es_es/amazonswf/latest/awsflowguide/details.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/es_es/amazonswf/latest/awsflowguide/details.html)  | 
| Reproducción | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/es_es/amazonswf/latest/awsflowguide/details.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/es_es/amazonswf/latest/awsflowguide/details.html)  | 
| Reproducción | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/es_es/amazonswf/latest/awsflowguide/details.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/es_es/amazonswf/latest/awsflowguide/details.html)  | 

Cuando se realiza una llamada a `processImage`, el marco de trabajo crea una nueva instancia de flujo de trabajo en Amazon SWF. Se trata de un registro duradero de la instancia de flujo de trabajo que se está iniciando. El programa se ejecuta hasta la llamada a la actividad `downloadImage` que pide a Amazon SWF que programe una actividad. El flujo de trabajo se sigue ejecutando y crea tareas para las actividades posteriores, pero no se pueden ejecutar hasta que la actividad `downloadImage` se complete; por lo tanto, este episodio de reproducción finaliza. Amazon SWF envía la tarea de la actividad `downloadImage` para que se ejecute y, una vez finalizada, se registra en el historial junto con el resultado. El flujo de trabajo está ahora listo para avanzar y Amazon SWF genera una tarea de decisión. El marco de trabajo recibe la tarea de decisión y reproduce el flujo de trabajo incorporando el resultado de las imágenes descargadas tal y como está registrado en el historial. Esto desbloquea la tarea de `createThumbnail`, y la ejecución del programa continúa avanzando con la programación de la tarea de actividad `createThumbnail` en Amazon SWF. Se repite el mismo proceso para `uploadImage`. La ejecución del programa sigue su curso hasta que el flujo de trabajo ha procesado todas las imágenes y no hay tareas pendientes. Como ningún estado de ejecución se almacena localmente, es posible que cada tarea de decisión se ejecute en una máquina diferente. Esto le permite escribir fácilmente programas que sean tolerantes a errores y fácilmente escalables.

## No determinismo
<a name="details.non"></a>

Como el marco se basa en la reproducción, es importante que el código de orquestación (todo el código del flujo de trabajo, con la excepción de las implementaciones de actividades) sea determinista. Por ejemplo, el flujo de control en su programa no debería depender de un número aleatorio o de la hora actual. Como estas cosas cambiarán entre las invocaciones, es posible que la reproducción no siga el mismo camino a través de la lógica de orquestación. Esto llevará a errores o resultados imprevistos. El marco de trabajo proporciona un `WorkflowClock` que puede utilizar para obtener la hora actual de manera determinista. Consulte la sección en [Contexto de ejecución](executioncontext.md) para obtener más información. 

**nota**  
Una conexión de Spring incorrecta de objetos de implementación de flujo de trabajo también puede llevar al no determinismo. Los beans de implementación de flujo de trabajo así como los bean de los que dependen tienen que estar dentro del alcance del flujo de trabajo (`WorkflowScope`). Por ejemplo, la conexión de un bean de implementación de flujo de trabajo a un bean que mantiene estado y está dentro del contexto global dará como resultado un comportamiento inesperado. Consulte la sección [Integración con Spring](test.md#test.spring) para obtener más información.