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 responses).
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 storage(s).
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 storages.
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 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:
In a RAM storage the data is entirely stored in
the client's memory. The server is never accessed. There is no data
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 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.
A compound storage is created by combining the storages of different models.
In this example there are two storages:
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.
_______________________________________________ Zope3-dev mailing list Zope3firstname.lastname@example.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com