[Zope3-dev] [ANIM] Compound storages (cpsskins)
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
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
be widget libraries.
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:
* Local (stores the data in cookies)
* Remote (accesses a remote server)
* Compound (a combination of several storages)
In a *RAM storage* the data is entirely stored in the client's memory.
The server is never accessed. There is no data persistence.
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.
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
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
The user input is *validated* before the data is getting stored.
Finally the view gets refreshed when the model is updated.
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...
More information about the Zope3-dev