|
Akka/Scala example source code file (migration-guide-persistence-experimental-2.3.x-2.4.x.rst)
The migration-guide-persistence-experimental-2.3.x-2.4.x.rst Akka example source code.. _migration-guide-persistence-experimental-2.3.x-2.4.x: ########################################################################## Migration Guide Akka Persistence (experimental) 2.3.3 to 2.3.4 (and 2.4.x) ########################################################################## **Akka Persistence** is an **experimental module**, which means that neither Binary Compatibility nor API stability is provided for Persistence while under the *experimental* flag. The goal of this phase is to gather user feedback before we freeze the APIs in a major release. Renamed EventsourcedProcessor to PersistentActor ================================================ ``EventsourcedProcessor`` is now deprecated and replaced by ``PersistentActor`` which provides the same (and more) API. Migrating to ``2.4.x`` is as simple as changing all your classes to extending ``PersistentActor``. Replace all classes like:: class DeprecatedProcessor extends EventsourcedProcessor { def processorId = "id" /*...*/ } To extend ``PersistentActor``:: class NewPersistentProcessor extends PersistentActor { def persistenceId = "id" /*...*/ } Read more about the persistent actor in the :ref:`documentation for Scala <event-sourcing>` and :ref:`documentation for Java <event-sourcing-java>`. Changed processorId to (abstract) persistenceId =============================================== In Akka Persistence ``2.3.3`` and previously, the main building block of applications were Processors. Persistent messages, as well as processors implemented the ``processorId`` method to identify which persistent entity a message belonged to. This concept remains the same in Akka ``2.3.4``, yet we rename ``processorId`` to ``persistenceId`` because Processors will be removed, and persistent messages can be used from different classes not only ``PersistentActor`` (Views, directly from Journals etc). Please note that ``persistenceId`` is **abstract** in the new API classes (``PersistentActor`` and ``PersistentView``), and we do **not** provide a default (actor-path derrived) value for it like we did for ``processorId``. The rationale behind this change being stricter de-coupling of your Actor hierarchy and the logical "which persistent entity this actor represents". A longer discussion on this subject can be found on `issue #15436 <https://github.com/akka/akka/issues/15436>`_ on github. In case you want to perserve the old behavior of providing the actor's path as the default ``persistenceId``, you can easily implement it yourself either as a helper trait or simply by overriding ``persistenceId`` as follows:: override def persistenceId = self.path.toStringWithoutAddress We provided the renamed method also on already deprecated classes (Channels), so you can simply apply a global rename of ``processorId`` to ``persistenceId``. Removed Processor in favour of extending PersistentActor with persistAsync ========================================================================== The ``Processor`` is now deprecated since ``2.3.4`` and will be removed in ``2.4.x``. It's semantics replicated in ``PersistentActor`` in the form of an additional ``persist`` method: ``persistAsync``. In essence, the difference betwen ``persist`` and ``persistAsync`` is that the former will stash all incomming commands until all persist callbacks have been processed, whereas the latter does not stash any commands. The new ``persistAsync`` should be used in cases of low consistency yet high responsiveness requirements, the Actor can keep processing incomming commands, even though not all previous events have been handled. When these ``persist`` and ``persistAsync`` are used together in the same ``PersistentActor``, the ``persist`` logic will win over the async version so that all guarantees concerning persist still hold. This will however lower the throughput Now deprecated code using Processor:: class OldProcessor extends Processor { override def processorId = "user-wallet-1337" def receive = { case Persistent(cmd) => sender() ! cmd } } Replacement code, with the same semantics, using PersistentActor:: class NewProcessor extends PersistentActor { override def persistenceId = "user-wallet-1337" def receiveCommand = { case cmd => persistAsync(cmd) { e => sender() ! e } } def receiveRecover = { case _ => // logic for handling replay } } It is worth pointing out that using ``sender()`` inside the persistAsync callback block is **valid**, and does *not* suffer any of the problems Futures have when closing over the sender reference. Using the ``PersistentActor`` instead of ``Processor`` also shifts the responsibility of deciding if a message should be persisted to the receiver instead of the sender of the message. Previously, using ``Processor``, clients would have to wrap messages as ``Persistent(cmd)`` manually, as well as have to be aware of the receiver being a ``Processor``, which didn't play well with transparency of the ActorRefs in general. Removed deleteMessage ===================== ``deleteMessage`` is deprecated and will be removed. When using command sourced ``Processor`` the command was stored before it was received and could be validated and then there was a reason to remove faulty commands to avoid repeating the error during replay. When using ``PersistentActor`` you can always validate the command before persisting and therefore the stored event (or command) should always be valid for replay. ``deleteMessages`` can still be used for pruning of all messages up to a sequence number. Renamed View to PersistentView, which receives plain messages (Persistent() wrapper is gone) ============================================================================================ Views used to receive messages wrapped as ``Persistent(payload, seqNr)``, this is no longer the case and views receive the ``payload`` as message from the ``Journal`` directly. The rationale here is that the wrapper aproach was inconsistent with the other Akka Persistence APIs and also is not easily "discoverable" (you have to *know* you will be getting this Persistent wrapper). Instead, since ``2.3.4``, views get plain messages, and can use additional methods provided by the ``View`` to identify if a message was sent from the Journal (had been played back to the view). So if you had code like this:: class AverageView extends View { override def processorId = "average-view" def receive = { case Persistent(msg, seqNr) => // from Journal case msg => // from user-land } You should update it to extend ``PersistentView`` instead:: class AverageView extends PersistentView { override def persistenceId = "persistence-sample" override def viewId = "persistence-sample-average" def receive = { case msg if isPersistent => // from Journal val seqNr = lastSequenceNr // in case you require the sequence number case msg => // from user-land } } In case you need to obtain the current sequence number the view is looking at, you can use the ``lastSequenceNr`` method. It is equivalent to "current sequence number", when ``isPersistent`` returns true, otherwise it yields the sequence number of the last persistent message that this view was updated with. Removed Channel and PersistentChannel in favour of AtLeastOnceDelivery trait ============================================================================ One of the primary tasks of a ``Channel`` was to de-duplicate messages that were sent from a ``Processor`` during recovery. Performing external side effects during recovery is not encouraged with event sourcing and therefore the ``Channel`` is not needed for this purpose. The ``Channel`` and ``PersistentChannel`` also performed at-least-once delivery of messages, but it did not free a sending actor from implementing retransmission or timeouts, since the acknowledgement from the channel is needed to guarantee safe hand-off. Therefore at-least-once delivery is provided in a new ``AtLeastOnceDelivery`` trait that is mixed-in to the persistent actor on the sending side. Read more about at-least-once delivery in the :ref:`documentation for Scala <at-least-once-delivery>` and :ref:`documentation for Java <at-least-once-delivery-java>`. Other Akka source code examplesHere is a short list of links related to this Akka migration-guide-persistence-experimental-2.3.x-2.4.x.rst source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.