RFC Name : Event Handling

Editor(s): BrianTurner DanielAbel

Date: Nov 21 2008

Status: Draft

TableOfContents([2])

Proposal

A lot of hacks are used in the event handling framework in cytoscape 2.x. We don't want 3.0 to look like that, so rethinking the complete framework for firing, listening to and handling events is needed.

Background

Many parts of cytoscape (both 2.6 and 3.0) use the [http://en.wikipedia.org/wiki/Observer_pattern Observer pattern]. There is a consensus that a naive implementation of the observer pattern would not be good enough for two main reasons:

Terminology used on this page

from Effective Java:

For example CyNetworkView is 'core code' when talking about the viewmodel API, and 'client code' when talking about the model API. When talking about the model API, CyNetworkView is just something that uses that API, just as a network analysis plugin would. When talking about the model API, CyNtworkView should not be in a special position (more special than being an important usecase; it is certainly not the only usecase.)

We should make the following distinction:

For example, in the current svn trunk, calling CyNetwork.addNode() triggers an AddedNode event, but the firing is done in core code (in the implementation of addNode())

from [http://en.wikipedia.org/wiki/Observer_pattern Observer pattern] terminology:

We also need to talk about

Decisions so far

In the following points a decision has basically been made, since a consensus emerged:

pull changeset design

The event object should contain enough information so that for most usecases the Observer does not need to query the Subject to handle the event. Since in theory Observers can do anything they want in the event-handling code, we can't guarantee that everything needed will be in the changeset, but it should be complete enough for the common usecases.

event framework uses OSGi internally

Listeners register via OSGi and the event framework will use OSGi to look them up, i.e. a whiteboard pattern is used. See [http://www.osgi.org/wiki/uploads/Links/whiteboard.pdf OSGI White Boarding]

raw toolkit events are turned into semantic 'action' events

The Presentation layer turns swing (or other toolkit) events into high-level abstract events. For a list of these events, see 'Presentation Events' in [:Cytoscape_3.0/EventHandling/PlannedCoreEventsIn3.0:]. Plugins will listen to these events, not to raw toolkit events.

This mapping from raw toolkit events to high-level abstract events will be made by an EventBroker, which will allow the user to modify this mapping, and provide some support for handling the case when plugins want to exclusively handle certain events, i.e. where Observers are not independent. (I.e. ask the user what to do; see [:Cytoscape_3.0/MiniRetreatTwo:] for details)

(Note that some think that drag/drop may have to be a special case; the following is from an earlier version of this page, and I am not sure what it means exactly:

Is this settled yet? -- DanielAbel)

Open questions

These are issues where no decision has been made yet.

representing events that belong together

This is the main topic of discussion.

In general, events will not be completely independent: a single semantical operation by an Actor will, in general result in triggering multiple events. This means that Actors will be removing multiple nodes at once, or replacing nodes with others, or opening a network.

The events that will be fired will generally represent lower-level operations. This means that it would make sense to handle a bunch of events together due to not only performance reasons, but also because other parts of the framework (undo/redo, etc.) could use events better.

Ideas:

  1. Batching: The case where many events (like the creation of many nodes) could possibly be grouped together as opposed to handling each one discretely.

    • What does batching mean? In Eclipse a batch is defined as set of nested events:

      It is important to note that the broadcast does not necessarily occur immediately after the method completes. This is because a resource changing operation may be nested inside of another operation. In this case, notification only occurs after the top-level operation completes. For example, calling IFile.move may trigger calls to IFile.create to create the new file, and then IFile.delete to remove the old file. Since the creation and deletion operations are nested inside the move operation, there will only be one notification.

  2. Transactions: Actors should leave the model in a valid state, and conflicting changes by different actors prevented. However not everything is editing. Some plugins may be passive, providing a view like an outline, in which case they should not have to concern themselves with the added complexities implied by participating in a transaction. In Eclipse a contributor to a perspective extends/implements either IViewPart or IEditorPart to help make this distinction in roles.

per-instance or per-class firing/listening?

The current implementation in core3 in svn trunk allows 'per-class' registration for a given event, i.e. the Observer gets all events of that type. The Observer is responsible for filtering out which events were fired for the instance it is interested in.

The alternative here is to allow 'per-instance' registration, where one registers as an Observer for the events of some Subject instances. In this case, the event framework would filter events to some extent, and each Observer would get somewhat fewer events it is not interested in.

what a Event object looks like

Depending on what overall design we select for the event framework, the event objects would look significantly different. Note that to a large extent the details of what an event object looks like are defined by the overall design. Since the overall design is not decided yet, the points mentioned here are largely only 'implementation details', for now.

Issues and concerns

The following is an outline of what any solution should consider

Note that we don't have to address all of these at once. (There is a considerable consensus that a 'full solution' is impossible.) It should be pretty explicit which issues a proposal would handle and which it would ignore.

guidelines for evaluating proposals

(from cyto-staff)

Dependent design choices

How we design certain parts of 3.0 will be influenced by the design of the event-handling framework. Proposals should consider these as usecases and discuss whether they provide partial solutions for implementing these features. Even if these features are not provided by the event framework 'for free', we should consider how much an approach helps or hinders implementing these

Prototypes

1. Svn+ssh://Grenache.ucsd.edu/cellar/common/svn/csplugins/trunk/Agilent/creech/BAMEventModel

2.

Issues

Batching

The problem with batching can be imagined in this way: When deleting a node (especially now that nodes exist w.r.t. only to a model, and not independently of it), listeners need to know about the node AND its context before the node is actually deleted. Thus, in a batch of events, with a naieve implementation, the node would already be gone by the time the batch was received. To circumvent this you might flag the node as being "marked for deletion", but this means, for the duration of the batch, every piece of the code the examines and graph and its nodes, needs to be sensitive to this state. (Updates can present similar issues, but deletion is the best example.)

Why did we want batching? Originally to address the issue of excess "noise". It should be noted that there are ways of reducing noise without batching all events. You, could for instance, just batch similar event types. However the failure to be able to apply a batch to any and all events means concepts like transactions if they are to be arbitrarily defined as a 'unit of work' independently of the code being batched is not possible.

Why not deal with batching later? Because batching (in a transactional sense, or any other higher level abstraction that groups events) does appear to be implementable without making changes to the API, something we wish to avoid in future releases. This is an assumption and it is possible someone might think of a way to introduce batching or transactions later on that don't affect the API, but in building the two prototypes, this does not seem likely.

Do we care about transactions? Isn't easier to leave them out? It is, as we discovered, however that was not our original intuition. We all thought batching would be easy. As well, introducing higher level abstractions about events, like "Undo/Redo" and "Transactions" seems like a natural progression in event handling, like hyper edges and group nodes in graphs. While the need for these things may not exist now, it doesn't seem unreasonable to imagine that we might at some future point, wish we had these capabilities and it is likely that other people will think as we did, that batching is natural extension to event handling, but of course, allowing for it comes with a price. Batching may come at such a price that the trade offs don't make it worth it.

Event Examples

Comments

Everything above should be either facts or consensus (unless clearly marked as being a non-consensus opinion), put comments here:

Funding for Cytoscape is provided by a federal grant from the U.S. National Institute of General Medical Sciences (NIGMS) of the Na tional Institutes of Health (NIH) under award number GM070743-01. Corporate funding is provided through a contract from Unilever PLC.

MoinMoin Appliance - Powered by TurnKey Linux