Cancer diagnosis and treatment
The last few weeks have been quite eventful. On October 21st this year, I received
On a new versioning approach for Zope-based applications
To make it short: CMFEditions stinks.
Why?
CMFEditions uses the ZODB for storing the state of an object as a Python pickle. The new versioning systems supports a pluggable storage system where a version storage provides its functionality through a well-defined API (as defined through IVersionSupport). Three different storages come to my mind: (RDBMS, object databases like the ZODB and document-oriented databases like MongoDB). A version storage API may look like this:
class IVersionStorage(Interface): # methods used for IVersionSupport def store(id, version_data, revision_metadata): """ Store 'version_data' for a given 'id'. 'version_data' holds the data to be versioned (JSON format). 'revision_metadata' holds application-specific metadata for the particular version (e.g. revision date, creator uid, "revision is a major/minor revision) (JSON format). Returns revision number. """ def retrieve(id, revision): """ Return 'version_data' for a given 'id' and 'revision' """ def remove(id): """ Remove all revisions for a given object 'id' """ def has_revision(id, revision): """ Check if there is a revison 'revision' for a given object 'id' """ def remove_revision(id, revision): """ Remove a particular 'revision' for a given object 'id' """ def remove(id): """ Remove all revisions for a given object 'id' """ def list_revisions(id): """ Return all revisions (and their stored revison_metadata) stored for a particular content piece by its 'id'. """
Versioning is an application-level functionality. An application should have full control over the things to be versioned (recall that CMFEdition always persists the full object state). In order to make a particular object versionable we need a simple interface (either to be implemented directly by the object or through an adapter):
class IVersionSupport(Interface): """ API for retrieving data to be versioned from an object and restoring a previous state of an object. The data format is JSON. Objects must provide their unique ID through the 'id' field. This API applies to single objects only (no support for object collections). """ def getVersionableData(): """ Return versionable data (in JSON format) """ def restoreFromVersion(version_data): """ Restore object based on 'version_data' (JSON format) """
I created a rapid protoype using MongoDB as storage backend for the versioned data. A very basic implementation for Archetypes-based content has been implemented using adapter:
The overall implementation is actually very small and extensible. In fact it is possible to version almost all core Plone content-types (except object collections (like folders)) into MongoDB.
We are using MongoDB in an ongoing project and my experiences are very positive. MongoDB is very easy so install and run (much, much easier than a ZODB/ZEO server) and its document-oriented storage approach fits perfectly with the JSON data model. In addition: MongoDB is blazing fast (up 50.000 inserts per second measured), has a rich query API and provides a bunch of replication options.