[Zope3-dev] [ANIM] Compound storages (cpsskins)

Jean-Marc Orliaguet jmo at ita.chalmers.se
Sun Feb 5 08:32:09 EST 2006


Here is an implementation of "compound storages" in CPSSkins (this 
concerns the CPSSkins AJAX toolkit only so it also applies to Zope3 in 
general, or to any other server that can handle JSON requests and 

First of all, this is a great step towards simplifying the development 
of AJAX applications since it provides a complete abstraction between 
the model and the storage. The development model gets shifted from 
writing code in javascript that moves data around places to defining a 
consistent data model. It is not necessarily easier unless one is used 
to creating application by first creating a model as opposed to starting 
by creating skins.

A data model needs some form of storage. There are many types of 
storages (persistent, volatile, with synchronous access, with 
asynchronous access, fast, slow, with low latency, with high latency...).
An AJAX application needs different types of storages to manipulate data 
locally, to store the results of some user action on a server, to 
provide temporary persistence for instance when editing a document, ... 
There isn't one type storage that is best suited for everything.
In the CPSSkins AJAX toolkit, there are three types of base storages 
available: the RAM storage, the local storage (cookie-based), and the 
remote storage (that uses accessors to get and set data via a remote 
server, e.g. Zope3).

A problem that occurs in the MVC model when many types of storages are 
available is that since a given view (a widget) can only observe a 
single model,  all the data will have to be stored in the same place and 
in the same way unless there is an indirection between the model and the 

The "compound storage" makes it possible to combine several models to 
set their respective storages in common. The "compound storage" is 
similar to a RAID controller: it uses several storages to create what 
looks like a single storage, also it dispatches the I/O to the different 

In the current implementation, the storages communicate with the 
compound storage and the compound storage communicates with the model 
using a simple event system (publish-subscribe with a extra message).

When some data gets stored in a given storage, an event is sent to the 
subscribers (e.g. the compound storage). The event then gets propagated 
to the model which relays the event to the view(s) which in turn get 
updated. This is completely event-driven, so no "user-space" controller 
is involved. The advantage is that it can occur asynchronously.

The compound storage defines a list of partitions. Each partition 
corresponds to the storage associated to a given model. The data stored 
in a model is accessed according to a schema which means that storages 
are protected against data corruption (such as changing the type of a 
field, or adding an unknown field).

There is a lot of complexity in the toolkit implementation, but this is 
as much complexity that gets hidden from the application: the controller 
simply needs to set data in the model it doesn't have to know anything 
about ajax.requests or cookies. I've started writing a simple live chat 
application, and all in all the entire application code consists in 
about 40 lines of code in zope3 and in a 3Kb page template.

The model definition can be created TTW, since the data is represented 
in JSON data structures, it involves no javascript. The only part that 
is javascript-heavy is the part that renders the widget, but there will 
be widget libraries.

The animation:

The toolkit code:

The code in Zope3:

The page template:

Here is the text seen in the animation:

  CPSSkins: storage adapters

A *storage adapter* can be specified in the model definition to describe 
how the model will access the data.

There are 4 types of storages available:

    * RAM
    * Local (stores the data in cookies)
    * Remote (accesses a remote server)
    * Compound (a combination of several storages)

    RAM storage

In a *RAM storage* the data is entirely stored in the client's memory. 
The server is never accessed. There is no data persistence.

    Local storage

In a *local storage* the data is stored in a cookie on the client. The 
server is never accessed. There is data persistence as long as the 
cookie does not expire.

    Remote storage

In this example the data is stored *on the server* inside the session. 
This provides some persistence which means that the page can be reloaded 
or the user can leave and return to the page and the current data will 
be restored.

An extra delay has been added when retrieving and when storing data to 
simulate network or database latency. Calls are made *asynchronously* 
which means that the browser can load the page entirely before the data 
is retrieved.

The user input is *validated* before the data is getting stored.

Finally the view gets refreshed when the model is updated.

    Compound storage

A compound storage is created by combining the storages of different models.

In this example there are two storages:

    * A RAM storage for setting the status message on the client's side.
    * A remote storage for saving the answer and for setting the status
      message from the server's side.

Both storages are combined into a unique *compound storage*.

Hence the view (input box widget) still observes a unique model. The 
status message can be written to both by the client and by the server 
and the view will be automatically updated.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.zope.org/pipermail/zope3-dev/attachments/20060205/0c3d139f/attachment.htm

More information about the Zope3-dev mailing list