Dataflow async
Library ID dataflow-async
Latest version 1.0.5

Tasks

A task is defined to be something that calculates the value of an attribute. Examples of tasks include the lambda passed when creating an attribute and the transformation function between two attributes.

What distinguishes tasks from a simple function is the fact that they must ultimately produce an AttributeData instance. The problem is that it would be highly inconvenient for you, the end user of this library, to always create an instance to return since most of the time you'll need to return a Loaded instance in transformation functions. For this reason the return value of tasks is T, not AttributeData<T>: it is implied that when the task returns a value, the status is loaded.

How to return something different then? For this purpose all tasks accept as their receiver a WorkContext instance, from which we can create and throw a particular exception that conveys this meaning. For more information about receiver of functions see the Kotlin™ documentation.

This examples of transformations of an attribute will clarify:

import com.femastudios.dataflow.async.* import com.femastudios.dataflow.async.util.* import java.util.Random fun main() { val a = attributeOf(lazy = false) { //The receiver of this lambda is a WorkContext instance, so `this` is now a WorkContext println("this = " + (this is WorkContext)) //Verify that `this` is a `WorkContext` instance val ret = Random().nextInt(100) if(ret < 50) { throwError("Nasty error!") //<-- called on the WorkContext receiver } else { ret } } Thread.sleep(100) //Allow time for the attribute to compute println(a.value) //Will be either LOADED or ERROR, depending on random result }
Attribute<Integer> a = Attribute.of(workContext -> { //Since Java doesn't support the change of `this` in lambdas the WorkContext is passed as its first parameter final int ret = new Random().nextInt(100); if(ret < 50) { //Since Java cannot understand that a method can always throw an exception //we must use a different function that creates the exception and throw it ourselves throw workContext.errorException("Nasty error!"); } else { return ret; } }); Thread.sleep(1000); //Allow time for the attribute to compute System.out.println(a.getValue()); //Will be either LOADED or ERROR, depending on random result

In this example we declared a new attribute with a task: this task generates a random number and returns it if it is less than 50, otherwise throws an exception generated with the passed WorkContext. There are also more functions that allow you to pass an instance of NotLoaded.

Note that you must explicitly throw errors, and that any uncaught exception in tasks will propagate its way up to caller, similarly to what happens on fields.