On Fri, 2012-10-26 at 21:04 +0200, Patrick Ohly wrote:
I'm attaching the current API revision, a README which gives
SyncEvolution specific information and two example scripts.
I realized that the API has a conceptual problem that makes it a bit
harder to use; I didn't get it right in the example "search.py".
Right now, search.py calls ReadContacts each time it is told that new
contacts were added or old ones updated. It does the call for exactly
the affected contacts. The goal is to always have the actual contact
data, as soon as possible.
The problem is that ReadContacts() is defined as returning the contacts
in the requested range *at the time when the server processes the call*.
This can lead to the following situation:
- client receives "10 added at #0"
- client calls ReadContacts(0, 10)
- client receives "10 added at #0" (basically, 10 contacts were
- client calls ReadContacts(0, 10)
- server processes first ReadContacts(), returns initial 10 contacts
- server processes second ReadContacts(), returns same data again
This is not what the client intended. It wanted to get the data of all
new 20 contacts.
One way of solving this is to let the client detect the situation and
re-request data as needed. This ensures that eventually it gets all
data, but it doesn't avoid the re-transmission of data. Not good.
The other solution is to change the API as follows:
- Introduce a separate string ID for a contact. This ID is assigned
when a contact is first added to any view (i.e., it is the same in all
views) and reported to the client as part of an extended
void ContactsAdded(object view, int start, array ids)
New contacts were added to the view. The number
of new contacts is given via the size of the ids array.
The ID of each new contact is guaranteed to be the same
in all views. IDs may get reused after their contact got
removed from the last view it was contained in. In
particular there is no guarantee that it is persistent
across restarts of the PIM manager.
The contact which previously had index #start now
has index #start + count, etc.
- The string ID becomes part of the contact dictionary:
"id" = an opaque string which identifies the contact while it
exists inside any PIM Manager view. See ContactsAdded and ReadContacts.
- Change the ReadContacts() call so that it takes an array of these IDs
to determine which data is requested:
list of (int index, contact dicts) pairs ReadContacts(array ids)
Requests the data of the contacts idenfified via their IDs.
Only the data of contacts that are still part of the view
can be returned.
The returned list contains the current index of the
requested contact plus its data. -1 and an empty
dictionary are returned for contacts which can no longer
be read, for example because they were removed from the
view in the meantime or because the ID was simply
Note that the caller must process the call response after
all events via the ViewAgent interface. Otherwise the
index numbers are potentially out of sync and thus
unreliable. Doing this call asynchronously and dealing
with the response as part of the main event loop will do
the right thing automatically, because D-Bus guarantees
ordering of messages.
Making this explicit by returning data via another
org._01.pim.contacts.ViewAgent method was considered and
rejected a) for the sake of keeping this API simple and
b) to allow simple synchronous calls where it makes sense
(testing, for example).
Does this make sense?
Best Regards, Patrick Ohly
The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.