[Dev] Problem with collection notifications
John Anderson
john at osafoundation.org
Sat Sep 24 10:30:35 PDT 2005
I ran into a new problem with our notification design:
In many cases, for example when updating the UI, we change data which
will eventually cause a notification, but since those changes are being
made by the code that updates the UI, it doesn't make sense to cause a
notification. In some cases it can lead to an infinite loop: you get
notified, you update the UI, which changes the data, which causes a
notification, which updates the UI, repeating forever.
I added a feature to temporarily turn off notifications while updating
the UI. However this strategy only works for synchronous notifications
-- the asynchronous ones keep coming in. So the problem still exists.
We're going to eventually have to come up a way to temporarily ignore
notifications, whether synchronous or asynchronous.
John
Ted Leung wrote:
> At the collections review we talked about some dimensions of
> notification like systems. I'm going to rehash that as context for
> the rest of this message.
>
> 1. Sync versus Async - when does the message get generated? As soon
> as a change happens (synchronous) or is there some delay before the
> message is generated (asynchronous)
> 2. Push versus Pull (poll) - How does the application get the
> message? Callbacks are called when the message is generated? (push)
> Callbacks are called when the application indicates it is ready to
> process the notifications -- by calling some function (pull)
> 3. Transient versus Persistent - How is subscription information (who
> will be notified of changes) maintained?
>
> I'll point out that I don't think that it is necessary that we support
> all possible combinations of dimensions. This is more just to help
> people understand the design space of possibilities.
>
> In Chandler, we have severals ways in which the app can be notified of
> changes
>
> 1. Collection Notifications
> * These tell you about the contents of a collection - when items
> are added and removed from collections and when items in a collection
> are changed.
> * An item can subscribe to changes on a collection by adding
> itself to that collection's subscribers list and implementing an
> onCollectionEvent callback method
> * When an add/remove operation happens a notification message is
> generated and delivered to the callbacks of all subscribers
> * When an item in the collection is changed, a notification
> message is generated but is not delivered until mapChangesCallable is
> called. In Chandler this happens in the idle loop
> * This mix between sync/push and async/pull models within the
> collections framework is problematic -- see below for a proposed solution.
> * You can change the method which will be called as a callback by
> adding an onCollectionEventHandler attribute (whose value is the name
> of the method). It's not clear to me that we need this level of
> generality
> * The callback API for collections has been propagated up from the
> low level set API. This should probably be changed to something that
> doesn't expose the implementation details of collections.
>
> 2. Monitors
> * Monitors tell you about changes to any attribute named 'x',
> regardless of the kind of the item.
> * When you create a monitor you supply a callback which consists
> of an item and a method on that item.
> * When the the attribute is changed, the monitor code calls the
> callback -- Message generation is synchronous and message delivery is
> push based.
>
> So there are a few problems that we need to look at.
>
> 1. the mix of notification styles in the collections framework
> 2. different mechanism for registering callbacks
> 3. differing callback API's
>
> == Problem #1: the mix of notification styles
>
> We agreed at the review that we would like to have a single style
> for notifications. The driving consideration is for the app to be
> able to process notifications when it is ready to, which points to a
> pull/polling style model.
>
> I have succeeded in restructuring the notification code so that all
> notifications (add/remove/changed) are delivered when a single
> function is called. Even though some messages are generated
> synchrounously, they are queued until delivery, so as far as the
> application is concerned, notifications are now delivered push style,
> which makes it hard to tell whether the messages were generated
> synchronously or not. This function is a module function in
> osaf.pim.collections:
>
> deliverNotifications(repositoryView)
>
> You must pass the current view to deliverNotifications, since changes
> happen in a particular view. On possible improvement would be to
> make deliverNotificaitons a method on a repositoryView, but I don't
> know how Andi would feel about that, and I'm not convinced that would
> be an improvement.
>
> I have not checked this code in, but it is passing all the existing
> notification tests, and Chandler appears to be running smoothly.
>
> Every view has a notification queue (transient) attached to it, and
> deliverNotifications walks the queue delivering the messages. Now
> that we have the queue, it seems like this would be a good place to
> insert code to completely turn off notifications, or to try to
> eliminate duplicate notifications.
>
> == Problem #2: Differing callback registration
>
> Alec proposed a unified API for callback registration in the message
> below, but needing to understand the possible values for 3 parameters
> seems more complicated than calling the existing monitor and
> collections subscription API's, although I suppose I could be persuaded.
>
> == Problem #3: Differing callback APIs'
>
> The API's for collection callbacks and monitor callbacks methods are
> different.
>
> collection_callback(self, op, item, name, other, *args)
> op = the kind of change
> item = the item containing a set (the collection item)
> name = the name of the set attribute (always "rep" for collections)
> other = the item that was changed
> *args = grab bag, but mostly unused
>
> monitor_callback(self, op, item, attribute, *args)
> op = the kind of change
> item = the item changed
> attribute = the attribute that was changed (allowing you to use the
> callback for more than one monitor if you checked the attribute value)
> *args = grab bag
>
> You could make them more similar by:
>
> unified_callback(self, op, changedItem, changedValue, attribute=None,
> *args)
> For collections, attribute would be None, dropping the name is fine
> because it is a fixed value in the collections framework.
> For monitors, attribute would be the attribute that would be changed.
>
> Again, it's not clear how much work this actually saves. But I am
> open to suggestions
>
>
>
> Ted
> ----
> Ted Leung Open Source Applications Foundation (OSAF)
> PGP Fingerprint: 1003 7870 251F FA71 A59A CEE3 BEBA 2B87 F5FC 4B42
>
> On Sep 19, 2005, at 1:56 PM, Alec Flett wrote:
>
>> Also, didn't we talk about a unified notification API that sits on
>> top of the Monitors/watchers/notifications with similar callbacks and
>> all that sort of thing?
>>
>> The way I was imagining this was a singleton notification manager
>> class that has a single entrypoint for notification registration. It
>> would also be responsible for queuing up notifications, and would
>> have a method that "fires" these notifications that could be called
>> from an OnIdle loop.
>>
>> What's nice is that asynchronous notifications could be handled all
>> in one place, and it would be up to the front end's event loop to
>> call the method that "fires" the notifications, so all the
>> notifications would originate in the same place.
>>
>> It would hopefully (if this isn't too ambitious) persist the async
>> notification list, and rely on the other subscription mechanisms
>> (like Monitors) to persist synchronous notification lists.
>>
>> Here's some strawman code to get us started that uses Monitors and
>> Collection subscribers
>>
>>
>> class NotificationManager(...):
>> def QueueAsyncNotification(self, realTarget, realTargetMethod, ....):
>>
>> def FireIdleNotifications(self, ...):
>>
>> def RegisterCallback(self, targetItem, methodName, item=None,
>> attribute=None, synchronous=True):
>> if item is None:
>> if synchronous and attribute is not None:
>> Monitors.attach(target, methodName, 'set', attribute)
>> elsif isinstance(item, AbstractCollection):
>> if synchronous:
>> item.subscribers.add((targetItem, methodName))
>> else:
>> item.subscribers.add((self, 'QueueAsyncNotification',
>> ..))
>>
>>
>> Now you could say
>> notificationManager.RegisterCallback(self, 'onMyCollectionChanged',
>> mycollection)
>>
>> Obviously there are lots of combinations of
>> item/attribute/synchronous that we need to address here.. persisting
>> asynchronous callbacks is going to be tricky. We'd also need API
>> changes (like that change to AbstractCollection.subscribers) and
>> callback parameter unification, but its a start. What do people think?
>>
>> Alec
>>
>> Ted Leung wrote:
>>
>>> The action items that we agreed on at the collections code/design
>>> review are here: <http://wiki.osafoundation.org/bin/view/Journal/
>>> TedLeung20050912>
>>>
>>> One of the items is to move away from use of onValueChanged and go
>>> back to using constructors for creating various collection kinds.
>>> Unfortunately, this
>>> means that we wouldn't be able to use update to change existing
>>> instances in the repository. So we can't remove the
>>> onValueChanged stuff, so it doesn't
>>> make sense to duplicate the code in the collection item
>>> constructors. So I'm just going to leave the code the way that it
>>> is now.
>>>
>>> Ted
>>>
>>>
>>>
>>> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
>>>
>>> Open Source Applications Foundation "Dev" mailing list
>>> http://lists.osafoundation.org/mailman/listinfo/dev
>>
>>
>
> ----
>
> Ted Leung Open Source Applications Foundation (OSAF)
>
> PGP Fingerprint: 1003 7870 251F FA71 A59A CEE3 BEBA 2B87 F5FC 4B42
>
>
>
>------------------------------------------------------------------------
>
>_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
>
>Open Source Applications Foundation "Dev" mailing list
>http://lists.osafoundation.org/mailman/listinfo/dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osafoundation.org/pipermail/dev/attachments/20050924/8bc4df63/attachment.htm
More information about the Dev
mailing list