Merge pull request #18084 from ktoso/wip-schema-migration-omg-its-a-small-book-ktoso

+doc #17613 document persistence schema evolution
This commit is contained in:
Konrad Malawski 2015-08-14 11:31:01 +02:00
commit fd43ac7b8d
31 changed files with 5334 additions and 19 deletions

View file

@ -8,6 +8,8 @@ import akka.japi.Procedure;
import akka.japi.pf.ReceiveBuilder;
import akka.pattern.BackoffSupervisor;
import akka.persistence.*;
import akka.persistence.journal.EventAdapter;
import akka.persistence.journal.EventSeq;
import scala.Option;
import scala.concurrent.duration.Duration;
import scala.PartialFunction;

View file

@ -589,6 +589,46 @@ not accept more messages and it will throw ``AtLeastOnceDelivery.MaxUnconfirmedM
The default value can be configured with the ``akka.persistence.at-least-once-delivery.max-unconfirmed-messages``
configuration key. The method can be overridden by implementation classes to return non-default values.
.. _event-adapters-lambda:
Event Adapters
==============
In long running projects using event sourcing sometimes the need arises to detach the data model from the domain model
completely.
Event Adapters help in situations where:
- **Version Migrations** existing events stored in *Version 1* should be "upcasted" to a new *Version 2* representation,
and the process of doing so involves actual code, not just changes on the serialization layer. For these scenarios
the ``toJournal`` function is usually an identity function, however the ``fromJournal`` is implemented as
``v1.Event=>v2.Event``, performing the neccessary mapping inside the fromJournal method.
This technique is sometimes refered to as "upcasting" in other CQRS libraries.
- **Separating Domain and Data models** thanks to EventAdapters it is possible to completely separate the domain model
from the model used to persist data in the Journals. For example one may want to use case classes in the
domain model, however persist their protocol-buffer (or any other binary serialization format) counter-parts to the Journal.
A simple ``toJournal:MyModel=>MyDataModel`` and ``fromJournal:MyDataModel=>MyModel`` adapter can be used to implement this feature.
- **Journal Specialized Data Types** exposing data types understood by the underlying Journal, for example for data stores which
understand JSON it is possible to write an EventAdapter ``toJournal:Any=>JSON`` such that the Journal can *directly* store the
json instead of serializing the object to its binary representation.
Implementing an EventAdapter is rather stright forward:
.. includecode:: code/docs/persistence/PersistenceEventAdapterDocTest.java#identity-event-adapter
Then in order for it to be used on events coming to and from the journal you must bind it using the below configuration syntax:
.. includecode:: ../scala/code/docs/persistence/PersistenceEventAdapterDocSpec.scala#event-adapters-config
It is possible to bind multiple adapters to one class *for recovery*, in which case the ``fromJournal`` methods of all
bound adapters will be applied to a given matching event (in order of definition in the configuration). Since each adapter may
return from ``0`` to ``n`` adapted events (called as ``EventSeq``), each adapter can investigate the event and if it should
indeed adapt it return the adapted event(s) for it, other adapters which do not have anything to contribute during this
adaptation simply return ``EventSeq.empty``. The adapted events are then delivered in-order to the ``PersistentActor`` during replay.
.. note::
For more advanced schema evolution techniques refer to the :ref:`persistence-schema-evolution-scala` documentation.
.. _persistent-fsm-java-lambda:
Persistent FSM
@ -797,6 +837,8 @@ it must add
to the application configuration. If not specified, a default serializer is used.
For more advanced schema evolution techniques refer to the :ref:`persistence-schema-evolution-scala` documentation.
Testing
=======

View file

@ -604,10 +604,6 @@ configuration key. The method can be overridden by implementation classes to ret
Event Adapters
==============
.. note::
Complete documentation featuring use-cases and implementation examples for this feature will follow shortly.
In long running projects using event sourcing sometimes the need arises to detach the data model from the domain model
completely.
@ -641,11 +637,7 @@ indeed adapt it return the adapted event(s) for it, other adapters which do not
adaptation simply return ``EventSeq.empty``. The adapted events are then delivered in-order to the ``PersistentActor`` during replay.
.. note::
More advanced techniques utilising advanced binary serialization formats such as protocol buffers or kryo / thrift / avro
will be documented very soon. These schema evolutions often may need to reach into the serialization layer, however
are much more powerful in terms of flexibly removing unused/deprecated classes from your classpath etc.
For more advanced schema evolution techniques refer to the :ref:`persistence-schema-evolution-scala` documentation.
Storage plugins
===============
@ -836,6 +828,8 @@ it must add
to the application configuration. If not specified, a default serializer is used.
For more advanced schema evolution techniques refer to the :ref:`persistence-schema-evolution-scala` documentation.
Testing
=======

View file

@ -111,11 +111,13 @@ bytes to different objects.
Then you only need to fill in the blanks, bind it to a name in your :ref:`configuration` and then
list which classes that should be serialized using it.
.. _string-manifest-serializer-java:
Serializer with String Manifest
-------------------------------
The ``Serializer`` illustrated above supports a class based manifest (type hint).
For serialization of data that need to evolve over time the `SerializerWithStringManifest`
For serialization of data that need to evolve over time the ``SerializerWithStringManifest``
is recommended instead of ``Serializer`` because the manifest (type hint) is a ``String``
instead of a ``Class``. That means that the class can be moved/removed and the serializer
can still deserialize old data by matching on the ``String``. This is especially useful