+per #18559 TCK tests for highestSequenceNr not reset after journal message deletion

* added tests
* docs about highestSeqenceNr behaviour after message deletion
* clarification about highestSequenceNr in AsyncRecovery#asyncReadHighestSequenceNr and AsyncWriteJournal#asyncDeleteMessagesTo
This commit is contained in:
Evgeny Shepelyuk 2015-10-13 22:27:14 +03:00
parent b5412a1ee0
commit 4eaa77608c
5 changed files with 114 additions and 83 deletions

View file

@ -66,8 +66,8 @@ Architecture
case of sender and receiver JVM crashes.
* *AsyncWriteJournal*: A journal stores the sequence of messages sent to a persistent actor. An application can control which messages
are journaled and which are received by the persistent actor without being journaled. The storage backend of a journal is pluggable.
Persistence extension comes with a "leveldb" journal plugin, which writes to the local filesystem,
are journaled and which are received by the persistent actor without being journaled. Journal maintains *highestSequenceNr* that is increased on each message.
The storage backend of a journal is pluggable. Persistence extension comes with a "leveldb" journal plugin, which writes to the local filesystem,
and replicated journals are available as `Community plugins`_.
* *Snapshot store*: A snapshot store persists snapshots of a persistent actor's or a view's internal state. Snapshots are
@ -354,6 +354,8 @@ while still having access to the accumulated state during replays - by loading t
The result of the ``deleteMessages`` request is signaled to the persistent actor with a ``DeleteMessagesSuccess``
message if the delete was successful or a ``DeleteMessagesFailure`` message if it failed.
Message deletion doesn't affect highest sequence number of journal, even if all messages were deleted from journal after ``deleteMessages`` invocation.
Persistence status handling
---------------------------
Persisting, deleting and replaying messages can either succeed or fail.

View file

@ -50,8 +50,8 @@ Architecture
case of sender and receiver JVM crashes.
* *AsyncWriteJournal*: A journal stores the sequence of messages sent to a persistent actor. An application can control which messages
are journaled and which are received by the persistent actor without being journaled. The storage backend of a journal is pluggable.
Persistence extension comes with a "leveldb" journal plugin, which writes to the local filesystem,
are journaled and which are received by the persistent actor without being journaled. Journal maintains *highestSequenceNr* that is increased on each message.
The storage backend of a journal is pluggable. Persistence extension comes with a "leveldb" journal plugin, which writes to the local filesystem,
and replicated journals are available as `Community plugins`_.
* *Snapshot store*: A snapshot store persists snapshots of a persistent actor's or a view's internal state. Snapshots are
@ -341,6 +341,8 @@ while still having access to the accumulated state during replays - by loading t
The result of the ``deleteMessages`` request is signaled to the persistent actor with a ``DeleteMessagesSuccess``
message if the delete was successful or a ``DeleteMessagesFailure`` message if it failed.
Message deletion doesn't affect highest sequence number of journal, even if all messages were deleted from journal after ``deleteMessages`` invocation.
Persistence status handling
---------------------------
Persisting, deleting and replaying messages can either succeed or fail.

View file

@ -157,6 +157,31 @@ abstract class JournalSpec(config: Config) extends PluginSpec(config) {
receiverProbe2.expectNoMsg(200.millis)
}
"not reset highestSequenceNr after message deletion" in {
journal ! ReplayMessages(0, Long.MaxValue, Long.MaxValue, pid, receiverProbe.ref)
1 to 5 foreach { i receiverProbe.expectMsg(replayedMessage(i)) }
receiverProbe.expectMsg(RecoverySuccess(highestSequenceNr = 5L))
journal ! DeleteMessagesTo(pid, 3L, receiverProbe.ref)
receiverProbe.expectMsg(DeleteMessagesSuccess(3L))
journal ! ReplayMessages(0, Long.MaxValue, Long.MaxValue, pid, receiverProbe.ref)
4 to 5 foreach { i receiverProbe.expectMsg(replayedMessage(i)) }
receiverProbe.expectMsg(RecoverySuccess(highestSequenceNr = 5L))
}
"not reset highestSequenceNr after journal cleanup" in {
journal ! ReplayMessages(0, Long.MaxValue, Long.MaxValue, pid, receiverProbe.ref)
1 to 5 foreach { i receiverProbe.expectMsg(replayedMessage(i)) }
receiverProbe.expectMsg(RecoverySuccess(highestSequenceNr = 5L))
journal ! DeleteMessagesTo(pid, Long.MaxValue, receiverProbe.ref)
receiverProbe.expectMsg(DeleteMessagesSuccess(Long.MaxValue))
journal ! ReplayMessages(0, Long.MaxValue, Long.MaxValue, pid, receiverProbe.ref)
receiverProbe.expectMsg(RecoverySuccess(highestSequenceNr = 5L))
}
"reject non-serializable events" in {
// there is no chance that a journal could create a data representation for type of event
val notSerializableEvent = new Object { override def toString = "not serializable" }

View file

@ -51,6 +51,7 @@ trait AsyncRecovery {
* number after recovery as the starting point when persisting new events.
* This sequence number is also used as `toSequenceNr` in subsequent call
* to [[#asyncReplayMessages]] unless the user has specified a lower `toSequenceNr`.
* Journal must maintain the highest sequence number and never decrease it.
*
* This call is protected with a circuit-breaker.
*

View file

@ -215,6 +215,7 @@ trait AsyncWriteJournal extends Actor with WriteJournalBase with AsyncRecovery {
* (inclusive).
*
* This call is protected with a circuit-breaker.
* Message deletion doesn't affect the highest sequence number of messages, journal must maintain the highest sequence number and never decrease it.
*/
def asyncDeleteMessagesTo(persistenceId: String, toSequenceNr: Long): Future[Unit]