Allow session observers to hook into the part of the session lifecycle before the session
subclasses start nuking things, but once it is known that it will end. It always bugged me in msoy that the session subclass has to do this (poorly). Seems patently observer-ish. This fix has almost no runtime overhead and is backwards compatible. The name isn't great, but I was leaving room for more methods in there should someone else find it useful, such as sessionWillStart or even clientObject[Will|Did]Release. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@6603 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -98,6 +98,20 @@ public class ClientManager
|
||||
void clientSessionDidEnd (PresentsSession session);
|
||||
}
|
||||
|
||||
/**
|
||||
* Methods for observing additional events in the session lifecycle.
|
||||
*/
|
||||
public static interface DetailedClientObserver extends ClientObserver
|
||||
{
|
||||
/**
|
||||
* Called prior to the sessions ending. Subclasses and this class tend to nuke a lot of
|
||||
* information in the process of ending. This will allow callers to act on session events
|
||||
* without creating a subclass of a session. For example lightweight management of dobj
|
||||
* fields such as flushing stats or notifying party members of a logout.
|
||||
*/
|
||||
void clientSessionWillEnd (PresentsSession session);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a client manager that will interact with the supplied connection manager.
|
||||
*/
|
||||
@@ -205,6 +219,9 @@ public class ClientManager
|
||||
public void addClientObserver (ClientObserver observer)
|
||||
{
|
||||
_clobservers.add(observer);
|
||||
if (observer instanceof DetailedClientObserver) {
|
||||
_dclobservers.add((DetailedClientObserver)observer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,6 +230,9 @@ public class ClientManager
|
||||
public void removeClientObserver (ClientObserver observer)
|
||||
{
|
||||
_clobservers.remove(observer);
|
||||
if (observer instanceof DetailedClientObserver) {
|
||||
_dclobservers.remove(observer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,9 +259,25 @@ public class ClientManager
|
||||
* Resolves the specified client, applies the supplied client operation to them and releases
|
||||
* the client.
|
||||
*/
|
||||
public void applyToClient (Name username, ClientOp clop)
|
||||
public void applyToClient (Name username, final ClientOp clop)
|
||||
{
|
||||
resolveClientObject(username, new ClientOpResolver(clop));
|
||||
resolveClientObject(username, new ClientResolutionListener() {
|
||||
public void clientResolved (Name username, ClientObject clobj) {
|
||||
try {
|
||||
clop.apply(clobj);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.warning("Client op failed", "username", username, "clop", clop, e);
|
||||
|
||||
} finally {
|
||||
releaseClientObject(username);
|
||||
}
|
||||
}
|
||||
|
||||
public void resolutionFailed (Name username, Exception reason) {
|
||||
clop.resolutionFailed(reason);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,6 +545,21 @@ public class ClientManager
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by PresentsSession when it is about to end its session.
|
||||
*/
|
||||
@EventThread
|
||||
protected void clientSessionWillEnd (final PresentsSession session)
|
||||
{
|
||||
// notify the observers that the session is ended
|
||||
_dclobservers.apply(new ObserverList.ObserverOp<DetailedClientObserver>() {
|
||||
public boolean apply (DetailedClientObserver observer) {
|
||||
observer.clientSessionWillEnd(session);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by PresentsSession when it has ended its session.
|
||||
*/
|
||||
@@ -575,33 +626,6 @@ public class ClientManager
|
||||
}
|
||||
}
|
||||
|
||||
/** Used by {@link ClientManager#applyToClient}. */
|
||||
protected class ClientOpResolver
|
||||
implements ClientResolutionListener
|
||||
{
|
||||
public ClientOpResolver (ClientOp clop) {
|
||||
_clop = clop;
|
||||
}
|
||||
|
||||
public void clientResolved (Name username, ClientObject clobj) {
|
||||
try {
|
||||
_clop.apply(clobj);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.warning("Client op failed", "username", username, "clop", _clop, e);
|
||||
|
||||
} finally {
|
||||
releaseClientObject(username);
|
||||
}
|
||||
}
|
||||
|
||||
public void resolutionFailed (Name username, Exception reason) {
|
||||
_clop.resolutionFailed(reason);
|
||||
}
|
||||
|
||||
protected ClientOp _clop;
|
||||
}
|
||||
|
||||
/** Used to resolve dependencies in {@link PresentsSession} instances that we create. */
|
||||
protected Injector _injector;
|
||||
|
||||
@@ -623,6 +647,9 @@ public class ClientManager
|
||||
/** Tracks registered {@link ClientObserver}s. */
|
||||
protected ObserverList<ClientObserver> _clobservers = ObserverList.newSafeInOrder();
|
||||
|
||||
/** Tracks registered {@link DetailedClientObserver}s. */
|
||||
protected ObserverList<DetailedClientObserver> _dclobservers = ObserverList.newSafeInOrder();
|
||||
|
||||
// our injected dependencies
|
||||
@Inject protected PresentsDObjectMgr _omgr;
|
||||
|
||||
|
||||
@@ -338,6 +338,8 @@ public class PresentsSession
|
||||
@EventThread
|
||||
public void endSession ()
|
||||
{
|
||||
_clmgr.clientSessionWillEnd(this);
|
||||
|
||||
// queue up a request for our connection to be closed (if we have a connection, that is)
|
||||
Connection conn = getConnection();
|
||||
if (conn != null) {
|
||||
|
||||
Reference in New Issue
Block a user