[Adium-devl] More design issues, and what I'm working on

David Smith catfish.man at gmail.com
Fri Nov 14 23:08:44 UTC 2008


	I'm sure most of those following commits have now seen my per-group  
visibility branch. It basically works, but has exposed two (or three,  
depending on how you count) difficult issues. Colin and I were  
discussing this yesterday but didn't come to all that many  
conclusions. The following is something of a braindump + request for  
ideas. On the upside though, Zac and I did figure out a pretty nice  
way of dealing with the previous issue I emailed the list about, which  
is now implemented in my branch.

	The first issue is propagating changes from the model (AIList* in  
this case) to the rest of Adium. We use ESObjectWithProperties +  
AIContactObserverManager for this currently. Prior to my recent  
changes, contained contacts would also notify their parent when they  
became visible or invisible. The logging enabled by http://trac.adiumx.com/changeset/25568 
  has turned up the expected result, which is that in certain  
circumstances (particularly when accounts sign off) we aren't re- 
sorting groups in response. This leads to visible and invisible  
contacts being mixed, which breaks an AIListGroup invariant (all  
visible contacts must be sorted first). I suspect the 'stale contacts'  
bugs that have been reported are also symptoms of this.
	We could attack this problem piecemeal and simply identify all the  
places we should be notifying and aren't, and fix them, but the whole  
system feels rather fragile. The bugs caused by not notifying properly  
are subtle and hard to diagnose, and can have very bad consequences.  
ESObjectWithProperties itself makes debugging harder (can't easily  
inspect object state in the debugger), is a performance issue with  
frequent property access (~10% of visibility calculation is spent  
accessing properties), and doesn't support keypaths; however, its  
delayed notification system is pretty essential.
	So, what to do? Bringing back direct containing object notification  
of visibility is difficult or impossible in a per-group visibility  
world. We could have groups watch all the properties that can change  
visibility of their contained objects, I suppose, and invalidate based  
on that. I've made a list of what those properties are, as far as I  
can tell:

online
idle
mobile
blocked
displayName
UID
containedObjects.visibility //when the number of visible objects in a  
container changes from 0 to 1 or vice versa, the container's  
visibility changes.

	The second issue is performance. By eliminating a lot of the caching  
we were doing, I've hurt contact list performance rather a lot. The  
new offline group design in my branch is even worse about this. My  
bad. My initial take on this is that it's actually a symptom of the  
first issue: the reason I eliminated caching in the first place was in  
an attempt to keep our state consistent and avoid breaking  
AIListGroup's invariants. This didn't work. A secondary benefit of it  
was that it allowed moving to per-group visibility, which is a  
requirement for contacts in multiple groups and making the offline  
group less complicated. I suspect that if we reintroduced visibility  
caching at the container level (an array or set of visible contacts)  
rather than the listobject level (a flag in AIListObject), and fixed  
the notification issues, this issue would go away.

	The third issue is a good deal more specific and maybe not a problem:  
we don't have a good way of getting a list of "top level" contacts.  
AIContactController has accessors for -allContacts (iterates the  
contacts dictionary and puts it in an array), -allMetaContacts (ditto  
for metas), and -allGroups. Unfortunately -allContacts includes ones  
that are contained in metas, so to get what I'm looking for I  
basically need to get allContacts, then subtract the contents of  
allMetaContacts from it. This means we can't effectively KVO "all  
contacts", and attempting to make the offline group into a filter on  
the contact list involves a bunch of iteration and adding and removing  
things from arrays, which hurts performance a lot.This sounds like  
maybe a good place to use the 'all contacts should be in metas' idea  
that's come up several times over the last year? Maybe it would be  
less of an issue with caching reinstated though. I'm not sure.




More information about the devel mailing list