below is a draft of the design doc for this feature. I have couple of conerns that I'd appreciate your feedback on.
HTTP Session passivation/activation feature design
* configuration (tomcat/resources/tc5/tc5-cluster-passivation-service.xml):
1. eviction policy configuration
2. cache loader configuration with passivation turned on
From JBossCache eviction policy implementation, The eviction policy is invoked based on the configured wakeup interval to process cache nodes (sessions) eviction based on the configured eviction policy attributes. The CachePassivation Interceptor will intercept the evict method calls on the nodes (sessions). It'll emit pre-passivation notification and store them in the configured passivation store (cache loader store) (filesystem or database).
When the node (session) is requested, it'll be loaded from JBossCacheManager.loadSession() which eventually calls cache.get(). It'll be intercepted by the ActivationInterceptor loading it from the passivation store (filesystem or database) and emits a post activation notification.
The notification emitted by the TreeCache will be broadcasted to the listeners that have registered with the TreeCache. In particluar, org.jboss.web.tomcat.tc5.session.CacheListener. Therefore its passivate or activate method will be invoked to notify the session listeners that the session is about to be passivated or has been activated. First, we check if the passivation/ activation event is emitted from a non-session FQN and this node (server) in the cluster, we skip it. Otherwise:
1) In passivate, we find the local session by calling JBossCacheManager.findLocalSession(). if the session found, call its passivate method.
2) In activate, we find the session by call calling JBossCacheManager.findSession() which will call loadSession if the data is outdated or the session doesn't exist in the manager's local store.
Concern: if the session is not found or outdated during activation, JBossCacheManager.loadSession() will be called and that trigger session.activate() which called from session.initAfterLoad(). That means, potentially, we call session.activate() twice. what should we do about it?
* passivate/activate methods
The session passivate/activate method is implemented in ClusteredSession to notify JBoss session attributes of type HttpSessionActivationListener, then it calls the StandardSession.passivate() or StandardSession.activate() to allow the catalina session to notify the catalina attributes of the type HttpSessionActivationListener as well.
* Flow control
JBossCacheManager.processExpires() is invoked from JBossManager.backgroundProcess() every 60 seconds (default) which expires idle session periodically. The logic of expire() is based on maxInactiveInterval which is set in JBossCacheManager.createSession(). In order to have a successful implementation here, we need to coordinate between backgroundProcess() and the eviction policy in use. Potentially, we have 2 different timers running here:
1) the eviction plicy which is enforced based on the wakeup interval (default 5 sec) set on the cache
2) the session time out based on maxInactiveInterval which is enforced by backgroundProcess() based on the configured value (default 60 seconds).
JBossCacheManager.processExpires() does the following:
2. iterate through the sessions
3. make sure that we're running in a transaction
4. check for the session data validity isOutdated(), which is set by the CacheListener when the node is identified to be dirty,
5. and session validity isValid(false). If the condition evalutes to true, the loadSession() is called which trigger activation. The activation will reset the last access time therefore, the session will be valid.
6. (concern) check the maxInactiveInterval by calling isValid() which in turn calls isValid(true) and if the session exceeded the maxInactiveInterval, it will be evicted from the cache, triggering passivation, and the session will be destroyed which makes it impossible to activate the session afterwords.
When the session exceeds maxInactiveInterval, should be removed not evicted from the cache. that will ensure that it'll be removed from the passivation store which will keep the passivation store in sync with cache at all time.
JBossCacheManager.stop() is invoked during AS shutdown. The first step in the stop process is to expire active sessions. When passivation is turned on, we should passivate those sessions instead of expiring them. That can be acheived by controlling the flow in JBossCacheManager.clearSessions(). if the passivation is turned on in the configuration file, then passivate sessions. Otherwise, just let the expiration take place.