javaterracottaobject-persistencechange-management

For persistent data in Terracotta, how to evolve classes?


We are considering Terracotta for our next project. I am intrigued by its potential to provide data persistence without the need for a separate DBMS. (See also On using Terracotta as a persistence solution)

One of the major pains of software evolution is to make the existing production data conform to the new data model. For an RDBMS you'd likely use a SQL change script at the moment of deployment. For Terracotta backed data, it is not immediately clear to me how to deal with non-trivial evolution.

There's a couple of paragraphs on Class Evolution in the Terracotta documentation but it seems specific to DSO and stays rather superficial.

  1. What are possible ways to handle data model evolution for the persistent data stored in Terracotta? I'm particularly interested in the non-DSO scenario (i.e. through the Terracotta Toolkit API).
  2. Do Terracotta DSO and the Toolkit API differ in their reactions to evolved class definitions?
  3. To understand the limitations of class evolution it would help to know how Terracotta represents/communicates object data; is there a specification for that?
  4. Maybe there are schema evolution techniques from the OODBMS world that are applicable to Terracotta?

As a trivial example, let's say I have a bunch of Car objects stored and I've changed the modelYear field of the Car class from a String to an int. According to the documentation this does not work out-of-the-box. I can imagine a solution where my old Car is loaded by a seperate classloader during application startup, and then converted to a new Car. Would that be a good approach and why (not)?


Solution

  • It depends on your use case scenario.

    If the cost of loading your cache is minimal (minutes) and you can afford down time...then I see no issue of simply rebuilding your cache for a new version.

    If you have high cost of populating your cache (hours/days) and you cannot afford any sizable downtime then you have to handle new and old version at the same time during transition period. For this:

    1. I would define a separate cache definition for any new version of the cached class and let old version to expire in the cache.
    2. Application code should have "old/new version" support as well.
    3. Have an instance that would still work with old version until data expires/obsolete (based on an old cache name)
    4. Have an instance that handled all new requests/flows with a new version (based on a new cache name)

    e.g. in ehcache.xml you would define 2 caches (based on your example):

    <cache name="com.xyz.Car" timeToLiveSeconds="600"/>
    <!--New version goes here-->
    <cache name="com.xyz.Car2" timeToLiveSeconds="600"/>
    

    In the long run, you should workout naming convention for your caches that includes version evolution.