Push node reference
Enable a node to invert the execution path and push data to a parent
Introduction
The goal is to invert the execution path order of two nodes. This allows a child node to push data to a parent node before the parent node OnEvent method is invoked.
Sometimes we want to push data to a shared node for reading by a sibling node. A problem can occur if the read node is not dependent upon the write node. As reader and writer are siblings their order in the execution path is not guaranteed, it is possible for the reader is notified first. This unpredictable behaviour is undesirable and difficult to understand and explain.
One solution is to force the reader to artificially create a dependency upon the writer. We want to move this error prone operation into the framework if possible, as a reader could easily miss this nuanced requirement.
In Fluxtion we use the @PushReference to mark a parent node as an inverted execution dependency. The child OnEvent method will be invoked before the parent OnEvent method.
If the writer specifies the parent node as a push reference then no reader will need to worry about execution order. The push creates an implicit dependency between reader and writer without the reader specifying anything and the processing will behave as expected.
Example
In this example we create a cache as a shared node, with a cache reader and cache writer. The reader and writer are siblings with no explicit dependency. We use the @PushReference
annotation in the writer to mark the cache as a push destination.
the code for the example is located here.
The node classes
public class Cache {
@OnEvent
public void reconcileCache(){}
}
public class CacheWriter {
@PushReference
public Cache cache;
private final MyEventHandler handler;
public CacheWriter(MyEventHandler handler) {
this.handler = handler;
}
public CacheWriter(Cache cache, MyEventHandler handler) {
this.cache = cache;
this.handler = handler;
}
@OnEvent
public void pushToCache(){}
}
public class CacheReader {
private final Cache cache;
private final MyEventHandler handler;
public CacheReader(Cache cache, MyEventHandler handler) {
this.cache = cache;
this.handler = handler;
}
@OnEvent
public void readFromCache() {}
}
SEPConfig builder
public class Builder extends SEPConfig {
@Override
public void buildConfig() {
MyEventHandler myHandler = addNode(new MyEventHandler());
Cache cache = addNode(new Cache());
CacheReader cacheReader = addNode(new CacheReader(cache, myHandler));
CacheWriter cacheWriter = addNode(new CacheWriter(cache, myHandler));
}
}
Generated SEP
The following SEP is generated by Fluxtion. Note that the event processing OnEvent methods is inverted for cache and cache writer. The reader is notified of a change after the cache update, behaving as expected.
public class SampleProcessor implements EventHandler, BatchHandler, Lifecycle {
//Node declarations
private final MyEventHandler myEventHandler_1 = new MyEventHandler();
private final CacheWriter cacheWriter_7 = new CacheWriter(myEventHandler_1);
private final Cache cache_3 = new Cache();
private final CacheReader cacheReader_5 = new CacheReader(cache_3, myEventHandler_1);
//omitted code for clarity
public void handleEvent(MyEvent typedEvent) {
//Default, no filter methods
myEventHandler_1.handleEvent(typedEvent);
cacheWriter_7.pushToCache();
cache_3.reconcileCache();
cacheReader_5.readFromCache();
//event stack unwind callbacks
afterEvent();
}
}
Generated png
The graphical representation of this execution graph as generated by Fluxtion ESC, shows the cache and writer inverted:

Example without @PushReference
As way of illustration we show the generated code and png if the @PushReference
annotation is removed from the CacheWriter.
Generated SEP
We can see the generated SEP implements counter-intuitive but correct behaviour as the reader accesses the cache before the writer has updated it.
public class SampleProcessor implements EventHandler, BatchHandler, Lifecycle {
//Node declarations
private final Cache cache_3 = new Cache();
private final MyEventHandler myEventHandler_1 = new MyEventHandler();
private final CacheReader cacheReader_5 = new CacheReader(cache_3, myEventHandler_1);
private final CacheWriter cacheWriter_7 = new CacheWriter(myEventHandler_1);
//Dirty flags
public void handleEvent(MyEvent typedEvent) {
//Default, no filter methods
myEventHandler_1.handleEvent(typedEvent);
cacheReader_5.readFromCache();
cacheWriter_7.pushToCache();
//event stack unwind callbacks
afterEvent();
}
//code omitted for clarity
}
Generated png
The image shows the CacheReader
and CacheWriter
are siblings with no explicit priority order. Also note because the Cache has no event handler parent nodes it is not included in any execution paths. Absence from an execution path means the reconcileCache()
method is never called.

Last updated
Was this helpful?