Session Iterator Functions
This section describes the four different APL sessionIterator functions. They can be used both for Real Time and Batch workflows.
An iterator is started with sessionIteratorCreate, and is ended by using sessionIteratorNext or aborted using sessionIteratorDestroy.
Iterating over all sessions in storage does not take any locks. This means that if a workflow updates the storage at the same time as the iteration is ongoing, sessions can be missed in the search or the same sessions can be returned twice. There is an "Error Count" on the iterator that can be used when this type of inconsistency has been detected. This is the same as the type of inconsistencies that can be detected in the Aggregation Session Inspector where sessions are not accessible.
The following functions for Session Iterator described here are:
sessionIteratorCreate
Creates a new iterator that can be used in the other three functions.
any sessionIteratorCreate( string profileName )
sessessionIteratorNext
Returns the next session or null if the full session storage has been traversed.
drudr sessionIteratorNext( any iterator )
sessionIteratorErrorCount
Returns the number of detected errors during the iteration. This is a fairly normal condition when the storage is updated or removed while the iteration is ongoing. Each error will typically mean that one session was missed, but it can also mean a larger number of missed sessions if the storage was moved.
If the session iterator starts iterating over the storage on one ec, and at the same time a workflow using the profile starts on another ec, the storage is removed from the first ec and started up at the second ec and the iterator will abort. This will be logged in system log as well as the error count being increased.
int sessionIteratorErrorCount( any iterator )
sessionIteratorDestroy
Destroy the iterator to release resources to avoid a memory leak due to iterators being left in live state. This is not needed if the iteration is run to the end.
void sessionIteratorDestroy( any iterator )
Best practice to implement sessionIterators in APL
An example below of searching for a session that matches an "intField" value.
"QueryData" is here the session type of the "Default.queryagg" profile.
QueryData findSession(int intFieldValue) { int retries = 0; any iter = null; // For a real scenario, consider limiting number of retries while (true) { iter = sessionIteratorCreate("Default.queryagg"); QueryData qd = (QueryData) sessionIteratorNext(iter); while (qd != null) { if (qd.intField == intFieldValue) { // Done! sessionIteratorDestroy(iter); return qd; } qd = (QueryData) sessionIteratorNext(iter); } if (sessionIteratorErrorCount(iter) > 0) { // We did not find the session and had errors -> retry ++retries; } else { // No errors, but it does not seem to exist return null; } } }
We simply retry the search whenever an error is detected. Note also the use of sessionIteratorDestroy which should be used whenever an iterator is not run to the end.
Performance Note!
Considerably better performance will be achieved by running the lookups on the same EC as the storage service. This means that if you run the lookup at the same time as a workflow using the storage is running on a different EC, then it will be slower. It will still be better performance than using the Aggregation Session Inspector, and there will be no load on the platform.