This site has been retired. For up to date information, see handbook.gnome.org or gitlab.gnome.org.


[Home] [TitleIndex] [WordIndex

Zeitgeist Engine API Draft

<!> This page is only a draft and is still work in progress

This page presents a new DBus API for the Zeitgeist engine. To help implement the API a data model as described Zeitgeist database design doc will be needed (unless the API is implemented on top of a full triple store like Tracker or KDEs Nepomuk work of course).

Design Ideas

Problem: Sorting

We have to carefully consider how we want to sort the results... There are three cases:

<!> Before we proceed much more with the design we should agree on a solution here...

Problem: Repository/Log Joins

While it is nice to separate the item and metadata repository from the event log it does incur some problems. We will likely need to do something equivalent to an SQL join between the two things. Ie. select items based on given log criteria and/or select events for a set of items meeting certain criteria.

We really want to avoid forcing ourselves to filter through large result sets. We also want to minimize the number of DBus roundtrips.

Interface: org.gnome.zeitgeist.Repository

The Zeitgeist engine needs detailed knowledge of all entities involved in the user's daily workflow in order to make proper guesses about usage patterns.

<!> FIXME: This interface needs to be completely reconsidered!

Item Struct

We will use the DBus signature I to represent an item corresponding to the signature sssssssay

GetItems

GetItems(in as uri_list, in b expand_annotations, out a(IaI) results)

Retrieve a collection of items given by their URIs, optionally expanding all annotations on each item. The returned values are in the same order as in uri_list.

FindAnnotations

FindAnnotations(in as target_filter, in as content_filter, in as source_filter, in as origin_filter, in as mimetype_filter, out FIXME)

Any empty filter denotes a wildcard

FindItems

FindAnnotations(in as content_filter, in as source_filter, in as origin_filter, in as mimetype_filter, out FIXME)

Any empty filter denotes a wildcard

SetItems

SetItems(in FIXME item_list)

DeleteItems

DeleteItems(in as uri_list)

Interface: org.gnome.zeitgeist.Log

This is the primary interface to access the Zeitgeist event log. It should be noted that events can be "promoted" to real items in the repository, in which case they can be the targets of annotations and other events!

Log Event Struct

For breveity we will use the bus signature E to describe (ssssu). This denotes an "event struct" containing:

LogEvents

LogEvents(in aE event_list, out as event_uris)

GetEvents

GetEvents(is as event_uris, out aE events)

Look up a set of events given their URIs

FindEvents

FindEvents(in as actor_filter, in as action_filter, in as subject_filter, in u time_start, in u time_end, in u offset, in u count, out aE)

For the *_filter arguments an empty string denotes a wildcard.

Event URI Construction

We should assign a URI to each logged event. The event URI should probably contain a timestamp of some sort. The catch here is that we might have more than 1 event is any given millisecond, so that alone wont make the event URI unique.

The event URIs does not have to include a lot of information. Their prime purpose is to be unique ids for each event. Something like the below should do:

zeitgeist://event/${system_time}/${global_sequence_number}

Here global_sequence_number is simply a long that is incremented by 1 each time we log an event.

Iterator Idea

The Find* methods could use the following approach to do cursoring over large result sets (we don't want to send 1M objects in one DBus message). The find methods take on an object path as an extra argument, this object is used as an iterator where more items can be requested - the find method itself returns the first batch of items. The object path to the iterator is fed into the method instead of being a return value to enable the caller to do "pipelining" of DBus requests - meaning that it doesn't have to wait for the response to Find*, it can simply issue a NextPage() on the iterator object straight after it has called Find*.

Example:

FindFoo (in o iter_path, in s what_foo, out as first_page)

The server will then bind on object on path iter_path with the following interface:

org.gnome.zeitgeist.Iterator.NextPage(in i max, out as values, out i offset)
org.gnome.zeitgeist.Iterator.Close()

A client could use this interface like this:

function receive_results(as values, i offset) {
   print "Got new page with data %s starting at %s" % (values, offset)
}

iter = CreateDBusProxy("/my/app/iter27", "org.gnome.zeitgeist.Iterator")
zeitgeist.FindFoo("/my/app/iter27", "this foo", async_result=receive_results)
// Don't wait for a reply, just continue fetching results!
iter.NextPage(20, async_result=receive_results)

2024-10-23 11:37