Implemented a Ray-proposed solution where we keep track of events that were

(pre-applied and) posted before we received our object but processed (and hence
dispatched to us) after we received our object.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4715 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2007-05-18 03:37:14 +00:00
parent db3fe80e9d
commit 9bcca099ac
10 changed files with 268 additions and 230 deletions
@@ -73,39 +73,19 @@ public class EntryAddedEvent<T extends DSet.Entry> extends NamedEvent
return _entry;
}
/**
* Applies this event to the object.
*/
@Override // from DEvent
public boolean alreadyApplied ()
{
return _alreadyApplied;
}
@Override // from DEvent
public boolean applyToObject (DObject target)
throws ObjectAccessException
{
if (!_alreadyApplied) {
if (!target.getSet(_name).add(_entry)) {
// If this entry is already in the set, then don't notify our listeners of the
// event add, because nothing was actually added; the DSet will have already
// complained; this happens occasionally due to a race condition between client
// object subscription and set addition, for example, the follow sequence of events
// can take place:
//
// 1. SUBSCRIBE arrives from client, AccessObjectEvent posted;
//
// 2. addToSet() called on server, value immediately added to set and
// EntryAddedEvent is posted;
//
// 3. AccessObjectEvent processed; client is added to proxy subscriber list,
// DObject serialized and sent to client; client receives object which already has
// the entry in the set;
//
// 4. EntryAddedEvent processed, client is a subscriber so it is forwarded along;
// when it arrives at the client, we find ourselves in this situation.
//
// Fixing this would require either a) giving up immediate adding to the DSet when
// an event is posted, but we add/update immediately because it makes our lives
// *vastly* simpler in a thousand other cases, or b) doing some magic in the DSet
// where the server "sees" the new entry added, but if the DSet is serialized
// before the EntryAddedEvent comes through to "commit" that entry it is not
// included. This is probably a good idea and maybe we'll do it sometime.
return false;
return false; // DSet will have already complained
}
}
return true;