+doc #17613 document persistence schema evolution
This commit is contained in:
parent
20352562e1
commit
270c566fea
31 changed files with 5334 additions and 19 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -586,6 +586,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
|
||||
|
|
@ -794,6 +834,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
|
||||
=======
|
||||
|
||||
|
|
|
|||
|
|
@ -601,10 +601,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.
|
||||
|
||||
|
|
@ -638,11 +634,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
|
||||
===============
|
||||
|
|
@ -833,6 +825,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
|
||||
=======
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue