For persistent data in Terracotta, how to evolve classes?
-
10-12-2019 - |
Question
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.
- 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).
- Do Terracotta DSO and the Toolkit API differ in their reactions to evolved class definitions?
- To understand the limitations of class evolution it would help to know how Terracotta represents/communicates object data; is there a specification for that?
- 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:
- I would define a separate cache definition for any new version of the cached class and let old version to expire in the cache.
- Application code should have "old/new version" support as well.
- Have an instance that would still work with old version until data expires/obsolete (based on an old cache name)
- 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.