Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
This context can be used to extend the {@link TaskContext#evaluate(Task)} algorithm with
* memoization behaviours specific to the {@link Task#type()}. This is specially useful when a
* type is backed by a an out-of-process store of some sort (database, service, etc).
*
*
By returning a value from {@link Memoizer#lookup(Task)}, this context will stop further
* evaluation of that tasks upstreams and short-circuit the evaluation algorithm at that task node.
* The resolved value will be used as input to dependent tasks
*
*
Example
*
*
{@code
* Tasks a, b and c depend on each other in a chain: a -> b -> c.
* // a depends on b, b depends on c
*
* When calling context.evaluate(a), this will be the sequence of calls made:
* context.evaluate(a)
* aMemoizer.lookup(a) => empty()
* context.evaluate(b)
* bMemoizer.lookup(b) => empty()
* context.evaluate(c)
* cMemoizer.lookup(c) => empty()
* cValue = context.invokeProcessFn(c, c.fn)
* cMemoizer.store(c, cValue)
* bValue = context.invokeProcessFn(b, b.fn)
* bMemoizer.store(b, bValue)
* aValue = context.invokeProcessFn(a, a.fn)
* aMemoizer.store(a, aValue)
*
* However, if any of the lookup calls return a value, the evaluation will short-circuit:
* context.evaluate(a)
* aMemoizer.lookup(a) => empty()
* context.evaluate(b)
* bMemoizer.lookup(b) => 'foo'
* // no expansion of upstreams to b
* aValue = context.invokeProcessFn(a, a.fn)
* aMemoizer.store(a, aValue)
* }
*
*
{@link Memoizer} implementations are discovered through the {@link Memoizer.Impl} annotations
* on a static method on the task type that should have the signature
* {@code public static Memoizer memoizer()}. The {@link Memoizer} type argument there should
* match the memoized type itself.
*/
public class MemoizingContext extends ForwardingTaskContext {
private static final Logger LOG = LoggerFactory.getLogger(MemoizingContext.class);
public interface Memoizer {
/**
* Marks a method with signature {@code public static Memoizer memoizer()}.
*
*
Can be called multiple times during an evaluation. The memoizer instance must not itself
* contain the memoizing context, but rather use an internal registry or store to keep track
* of stored values.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Impl { }
/**
* Lookup a memoized value for a given task.
*
* @param task The task for which the lookup is made
* @return An optional memoized value for the task
*/
Optional lookup(Task task);
/**
* Store an evaluated value for a given task.
*
* @param task The task for which the value was produced
* @param value The value that was produced
*/
void store(Task task, T value);
/**
* A memoizer that does nothing and always returns empty {@link #lookup} values
*/
static Memoizer noop() {
//noinspection unchecked
return (Memoizer) NOOP;
}
}
private static final Memoizer