* added to EventEnvolope and therefore include case class stuff for binary compatibility * also added in PersistentRepr, which for example is the serialized format in LeveldbJournal
This commit is contained in:
parent
290a6137e0
commit
efa856bc17
12 changed files with 287 additions and 34 deletions
|
|
@ -158,6 +158,17 @@ public final class MessageFormats {
|
|||
*/
|
||||
akka.protobufv3.internal.ByteString
|
||||
getWriterUuidBytes();
|
||||
|
||||
/**
|
||||
* <code>optional sint64 timestamp = 14;</code>
|
||||
* @return Whether the timestamp field is set.
|
||||
*/
|
||||
boolean hasTimestamp();
|
||||
/**
|
||||
* <code>optional sint64 timestamp = 14;</code>
|
||||
* @return The timestamp.
|
||||
*/
|
||||
long getTimestamp();
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code PersistentMessage}
|
||||
|
|
@ -256,6 +267,11 @@ public final class MessageFormats {
|
|||
writerUuid_ = bs;
|
||||
break;
|
||||
}
|
||||
case 112: {
|
||||
bitField0_ |= 0x00000080;
|
||||
timestamp_ = input.readSInt64();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (!parseUnknownField(
|
||||
input, unknownFields, extensionRegistry, tag)) {
|
||||
|
|
@ -558,6 +574,23 @@ public final class MessageFormats {
|
|||
}
|
||||
}
|
||||
|
||||
public static final int TIMESTAMP_FIELD_NUMBER = 14;
|
||||
private long timestamp_;
|
||||
/**
|
||||
* <code>optional sint64 timestamp = 14;</code>
|
||||
* @return Whether the timestamp field is set.
|
||||
*/
|
||||
public boolean hasTimestamp() {
|
||||
return ((bitField0_ & 0x00000080) != 0);
|
||||
}
|
||||
/**
|
||||
* <code>optional sint64 timestamp = 14;</code>
|
||||
* @return The timestamp.
|
||||
*/
|
||||
public long getTimestamp() {
|
||||
return timestamp_;
|
||||
}
|
||||
|
||||
private byte memoizedIsInitialized = -1;
|
||||
@java.lang.Override
|
||||
public final boolean isInitialized() {
|
||||
|
|
@ -599,6 +632,9 @@ public final class MessageFormats {
|
|||
if (((bitField0_ & 0x00000040) != 0)) {
|
||||
akka.protobufv3.internal.GeneratedMessageV3.writeString(output, 13, writerUuid_);
|
||||
}
|
||||
if (((bitField0_ & 0x00000080) != 0)) {
|
||||
output.writeSInt64(14, timestamp_);
|
||||
}
|
||||
unknownFields.writeTo(output);
|
||||
}
|
||||
|
||||
|
|
@ -632,6 +668,10 @@ public final class MessageFormats {
|
|||
if (((bitField0_ & 0x00000040) != 0)) {
|
||||
size += akka.protobufv3.internal.GeneratedMessageV3.computeStringSize(13, writerUuid_);
|
||||
}
|
||||
if (((bitField0_ & 0x00000080) != 0)) {
|
||||
size += akka.protobufv3.internal.CodedOutputStream
|
||||
.computeSInt64Size(14, timestamp_);
|
||||
}
|
||||
size += unknownFields.getSerializedSize();
|
||||
memoizedSize = size;
|
||||
return size;
|
||||
|
|
@ -682,6 +722,11 @@ public final class MessageFormats {
|
|||
if (!getWriterUuid()
|
||||
.equals(other.getWriterUuid())) return false;
|
||||
}
|
||||
if (hasTimestamp() != other.hasTimestamp()) return false;
|
||||
if (hasTimestamp()) {
|
||||
if (getTimestamp()
|
||||
!= other.getTimestamp()) return false;
|
||||
}
|
||||
if (!unknownFields.equals(other.unknownFields)) return false;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -723,6 +768,11 @@ public final class MessageFormats {
|
|||
hash = (37 * hash) + WRITERUUID_FIELD_NUMBER;
|
||||
hash = (53 * hash) + getWriterUuid().hashCode();
|
||||
}
|
||||
if (hasTimestamp()) {
|
||||
hash = (37 * hash) + TIMESTAMP_FIELD_NUMBER;
|
||||
hash = (53 * hash) + akka.protobufv3.internal.Internal.hashLong(
|
||||
getTimestamp());
|
||||
}
|
||||
hash = (29 * hash) + unknownFields.hashCode();
|
||||
memoizedHashCode = hash;
|
||||
return hash;
|
||||
|
|
@ -875,6 +925,8 @@ public final class MessageFormats {
|
|||
bitField0_ = (bitField0_ & ~0x00000020);
|
||||
writerUuid_ = "";
|
||||
bitField0_ = (bitField0_ & ~0x00000040);
|
||||
timestamp_ = 0L;
|
||||
bitField0_ = (bitField0_ & ~0x00000080);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -935,6 +987,10 @@ public final class MessageFormats {
|
|||
to_bitField0_ |= 0x00000040;
|
||||
}
|
||||
result.writerUuid_ = writerUuid_;
|
||||
if (((from_bitField0_ & 0x00000080) != 0)) {
|
||||
result.timestamp_ = timestamp_;
|
||||
to_bitField0_ |= 0x00000080;
|
||||
}
|
||||
result.bitField0_ = to_bitField0_;
|
||||
onBuilt();
|
||||
return result;
|
||||
|
|
@ -1013,6 +1069,9 @@ public final class MessageFormats {
|
|||
writerUuid_ = other.writerUuid_;
|
||||
onChanged();
|
||||
}
|
||||
if (other.hasTimestamp()) {
|
||||
setTimestamp(other.getTimestamp());
|
||||
}
|
||||
this.mergeUnknownFields(other.unknownFields);
|
||||
onChanged();
|
||||
return this;
|
||||
|
|
@ -1641,6 +1700,43 @@ public final class MessageFormats {
|
|||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
private long timestamp_ ;
|
||||
/**
|
||||
* <code>optional sint64 timestamp = 14;</code>
|
||||
* @return Whether the timestamp field is set.
|
||||
*/
|
||||
public boolean hasTimestamp() {
|
||||
return ((bitField0_ & 0x00000080) != 0);
|
||||
}
|
||||
/**
|
||||
* <code>optional sint64 timestamp = 14;</code>
|
||||
* @return The timestamp.
|
||||
*/
|
||||
public long getTimestamp() {
|
||||
return timestamp_;
|
||||
}
|
||||
/**
|
||||
* <code>optional sint64 timestamp = 14;</code>
|
||||
* @param value The timestamp to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setTimestamp(long value) {
|
||||
bitField0_ |= 0x00000080;
|
||||
timestamp_ = value;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional sint64 timestamp = 14;</code>
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder clearTimestamp() {
|
||||
bitField0_ = (bitField0_ & ~0x00000080);
|
||||
timestamp_ = 0L;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
@java.lang.Override
|
||||
public final Builder setUnknownFields(
|
||||
final akka.protobufv3.internal.UnknownFieldSet unknownFields) {
|
||||
|
|
@ -6963,27 +7059,27 @@ public final class MessageFormats {
|
|||
descriptor;
|
||||
static {
|
||||
java.lang.String[] descriptorData = {
|
||||
"\n\024MessageFormats.proto\"\252\001\n\021PersistentMes" +
|
||||
"\n\024MessageFormats.proto\"\275\001\n\021PersistentMes" +
|
||||
"sage\022#\n\007payload\030\001 \001(\0132\022.PersistentPayloa" +
|
||||
"d\022\022\n\nsequenceNr\030\002 \001(\003\022\025\n\rpersistenceId\030\003" +
|
||||
" \001(\t\022\017\n\007deleted\030\004 \001(\010\022\016\n\006sender\030\013 \001(\t\022\020\n" +
|
||||
"\010manifest\030\014 \001(\t\022\022\n\nwriterUuid\030\r \001(\t\"S\n\021P" +
|
||||
"ersistentPayload\022\024\n\014serializerId\030\001 \002(\005\022\017" +
|
||||
"\n\007payload\030\002 \002(\014\022\027\n\017payloadManifest\030\003 \001(\014" +
|
||||
"\"2\n\013AtomicWrite\022#\n\007payload\030\001 \003(\0132\022.Persi" +
|
||||
"stentMessage\"\356\001\n\033AtLeastOnceDeliverySnap" +
|
||||
"shot\022\031\n\021currentDeliveryId\030\001 \002(\003\022O\n\025uncon" +
|
||||
"firmedDeliveries\030\002 \003(\01320.AtLeastOnceDeli" +
|
||||
"verySnapshot.UnconfirmedDelivery\032c\n\023Unco" +
|
||||
"nfirmedDelivery\022\022\n\ndeliveryId\030\001 \002(\003\022\023\n\013d" +
|
||||
"estination\030\002 \002(\t\022#\n\007payload\030\003 \002(\0132\022.Pers" +
|
||||
"istentPayload\"\\\n\032PersistentStateChangeEv" +
|
||||
"ent\022\027\n\017stateIdentifier\030\001 \002(\t\022\017\n\007timeout\030" +
|
||||
"\002 \001(\t\022\024\n\014timeoutNanos\030\003 \001(\003\"h\n\025Persisten" +
|
||||
"tFSMSnapshot\022\027\n\017stateIdentifier\030\001 \002(\t\022 \n" +
|
||||
"\004data\030\002 \002(\0132\022.PersistentPayload\022\024\n\014timeo" +
|
||||
"utNanos\030\003 \001(\003B\"\n\036akka.persistence.serial" +
|
||||
"izationH\001"
|
||||
"\010manifest\030\014 \001(\t\022\022\n\nwriterUuid\030\r \001(\t\022\021\n\tt" +
|
||||
"imestamp\030\016 \001(\022\"S\n\021PersistentPayload\022\024\n\014s" +
|
||||
"erializerId\030\001 \002(\005\022\017\n\007payload\030\002 \002(\014\022\027\n\017pa" +
|
||||
"yloadManifest\030\003 \001(\014\"2\n\013AtomicWrite\022#\n\007pa" +
|
||||
"yload\030\001 \003(\0132\022.PersistentMessage\"\356\001\n\033AtLe" +
|
||||
"astOnceDeliverySnapshot\022\031\n\021currentDelive" +
|
||||
"ryId\030\001 \002(\003\022O\n\025unconfirmedDeliveries\030\002 \003(" +
|
||||
"\01320.AtLeastOnceDeliverySnapshot.Unconfir" +
|
||||
"medDelivery\032c\n\023UnconfirmedDelivery\022\022\n\nde" +
|
||||
"liveryId\030\001 \002(\003\022\023\n\013destination\030\002 \002(\t\022#\n\007p" +
|
||||
"ayload\030\003 \002(\0132\022.PersistentPayload\"\\\n\032Pers" +
|
||||
"istentStateChangeEvent\022\027\n\017stateIdentifie" +
|
||||
"r\030\001 \002(\t\022\017\n\007timeout\030\002 \001(\t\022\024\n\014timeoutNanos" +
|
||||
"\030\003 \001(\003\"h\n\025PersistentFSMSnapshot\022\027\n\017state" +
|
||||
"Identifier\030\001 \002(\t\022 \n\004data\030\002 \002(\0132\022.Persist" +
|
||||
"entPayload\022\024\n\014timeoutNanos\030\003 \001(\003B\"\n\036akka" +
|
||||
".persistence.serializationH\001"
|
||||
};
|
||||
descriptor = akka.protobufv3.internal.Descriptors.FileDescriptor
|
||||
.internalBuildGeneratedFileFrom(descriptorData,
|
||||
|
|
@ -6994,7 +7090,7 @@ public final class MessageFormats {
|
|||
internal_static_PersistentMessage_fieldAccessorTable = new
|
||||
akka.protobufv3.internal.GeneratedMessageV3.FieldAccessorTable(
|
||||
internal_static_PersistentMessage_descriptor,
|
||||
new java.lang.String[] { "Payload", "SequenceNr", "PersistenceId", "Deleted", "Sender", "Manifest", "WriterUuid", });
|
||||
new java.lang.String[] { "Payload", "SequenceNr", "PersistenceId", "Deleted", "Sender", "Manifest", "WriterUuid", "Timestamp", });
|
||||
internal_static_PersistentPayload_descriptor =
|
||||
getDescriptor().getMessageTypes().get(1);
|
||||
internal_static_PersistentPayload_fieldAccessorTable = new
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# #28331 Add optional timestamp to PersistentRepr
|
||||
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.persistence.PersistentRepr.timestamp")
|
||||
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.persistence.PersistentRepr.withTimestamp")
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.persistence.PersistentImpl.apply")
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.persistence.PersistentImpl.copy")
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.persistence.PersistentImpl.this")
|
||||
ProblemFilters.exclude[Problem]("akka.persistence.PersistentImpl*")
|
||||
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.persistence.serialization.MessageFormats#PersistentMessageOrBuilder.hasTimestamp")
|
||||
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.persistence.serialization.MessageFormats#PersistentMessageOrBuilder.getTimestamp")
|
||||
|
|
@ -20,6 +20,7 @@ message PersistentMessage {
|
|||
optional string sender = 11; // not stored in journal, needed for remote serialization
|
||||
optional string manifest = 12;
|
||||
optional string writerUuid = 13;
|
||||
optional sint64 timestamp = 14;
|
||||
}
|
||||
|
||||
message PersistentPayload {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import akka.persistence.serialization.Message
|
|||
import scala.collection.immutable
|
||||
|
||||
import akka.annotation.DoNotInherit
|
||||
import akka.util.HashCode
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
|
|
@ -91,6 +92,16 @@ final case class AtomicWrite(payload: immutable.Seq[PersistentRepr]) extends Per
|
|||
*/
|
||||
def sequenceNr: Long
|
||||
|
||||
/**
|
||||
* The `timestamp` is the time the event was stored, in milliseconds since midnight, January 1, 1970 UTC
|
||||
* (same as `System.currentTimeMillis`).
|
||||
*
|
||||
* Value `0` is used if undefined.
|
||||
*/
|
||||
def timestamp: Long
|
||||
|
||||
def withTimestamp(newTimestamp: Long): PersistentRepr
|
||||
|
||||
/**
|
||||
* Unique identifier of the writing persistent actor.
|
||||
* Used to detect anomalies with overlapping writes from multiple
|
||||
|
|
@ -152,7 +163,7 @@ object PersistentRepr {
|
|||
deleted: Boolean = false,
|
||||
sender: ActorRef = null,
|
||||
writerUuid: String = PersistentRepr.Undefined): PersistentRepr =
|
||||
PersistentImpl(payload, sequenceNr, persistenceId, manifest, deleted, sender, writerUuid)
|
||||
PersistentImpl(payload, sequenceNr, persistenceId, manifest, deleted, sender, writerUuid, 0L)
|
||||
|
||||
/**
|
||||
* Java API, Plugin API.
|
||||
|
|
@ -176,7 +187,8 @@ private[persistence] final case class PersistentImpl(
|
|||
override val manifest: String,
|
||||
override val deleted: Boolean,
|
||||
override val sender: ActorRef,
|
||||
override val writerUuid: String)
|
||||
override val writerUuid: String,
|
||||
override val timestamp: Long)
|
||||
extends PersistentRepr
|
||||
with NoSerializationVerificationNeeded {
|
||||
|
||||
|
|
@ -187,6 +199,10 @@ private[persistence] final case class PersistentImpl(
|
|||
if (this.manifest == manifest) this
|
||||
else copy(manifest = manifest)
|
||||
|
||||
override def withTimestamp(newTimestamp: Long): PersistentRepr =
|
||||
if (this.timestamp == newTimestamp) this
|
||||
else copy(timestamp = newTimestamp)
|
||||
|
||||
def update(sequenceNr: Long, persistenceId: String, deleted: Boolean, sender: ActorRef, writerUuid: String) =
|
||||
copy(
|
||||
sequenceNr = sequenceNr,
|
||||
|
|
@ -195,4 +211,25 @@ private[persistence] final case class PersistentImpl(
|
|||
sender = sender,
|
||||
writerUuid = writerUuid)
|
||||
|
||||
override def hashCode(): Int = {
|
||||
var result = HashCode.SEED
|
||||
result = HashCode.hash(result, payload)
|
||||
result = HashCode.hash(result, sequenceNr)
|
||||
result = HashCode.hash(result, persistenceId)
|
||||
result = HashCode.hash(result, manifest)
|
||||
result = HashCode.hash(result, deleted)
|
||||
result = HashCode.hash(result, sender)
|
||||
result = HashCode.hash(result, writerUuid)
|
||||
// timestamp not included in equals for backwards compatibility
|
||||
result
|
||||
}
|
||||
|
||||
override def equals(obj: Any): Boolean = obj match {
|
||||
case other: PersistentImpl =>
|
||||
payload == other.payload && sequenceNr == other.sequenceNr && persistenceId == other.persistenceId &&
|
||||
manifest == other.manifest && deleted == other.deleted &&
|
||||
sender == other.sender && writerUuid == other.writerUuid // timestamp not included in equals for backwards compatibility
|
||||
case _ => false
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ private[persistence] trait LeveldbStore
|
|||
def persistentFromBytes(a: Array[Byte]): PersistentRepr = serialization.deserialize(a, classOf[PersistentRepr]).get
|
||||
|
||||
private def addToMessageBatch(persistent: PersistentRepr, tags: Set[String], batch: WriteBatch): Unit = {
|
||||
val persistentBytes = persistentToBytes(persistent)
|
||||
val persistentBytes = persistentToBytes(persistent.withTimestamp(System.currentTimeMillis()))
|
||||
val nid = numericId(persistent.persistenceId)
|
||||
batch.put(keyToBytes(counterKey(nid)), counterToBytes(persistent.sequenceNr))
|
||||
batch.put(keyToBytes(Key(nid, persistent.sequenceNr, 0)), persistentBytes)
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ class MessageSerializer(val system: ExtendedActorSystem) extends BaseSerializer
|
|||
builder.setSequenceNr(persistent.sequenceNr)
|
||||
// deleted is not used in new records from 2.4
|
||||
if (persistent.writerUuid != Undefined) builder.setWriterUuid(persistent.writerUuid)
|
||||
if (persistent.timestamp > 0L) builder.setTimestamp(persistent.timestamp)
|
||||
builder
|
||||
}
|
||||
|
||||
|
|
@ -197,7 +198,7 @@ class MessageSerializer(val system: ExtendedActorSystem) extends BaseSerializer
|
|||
//
|
||||
|
||||
private def persistent(persistentMessage: mf.PersistentMessage): PersistentRepr = {
|
||||
PersistentRepr(
|
||||
val repr = PersistentRepr(
|
||||
payload(persistentMessage.getPayload),
|
||||
persistentMessage.getSequenceNr,
|
||||
if (persistentMessage.hasPersistenceId) persistentMessage.getPersistenceId else Undefined,
|
||||
|
|
@ -206,6 +207,8 @@ class MessageSerializer(val system: ExtendedActorSystem) extends BaseSerializer
|
|||
if (persistentMessage.hasSender) system.provider.resolveActorRef(persistentMessage.getSender)
|
||||
else Actor.noSender,
|
||||
if (persistentMessage.hasWriterUuid) persistentMessage.getWriterUuid else Undefined)
|
||||
|
||||
if (persistentMessage.hasTimestamp) repr.withTimestamp(persistentMessage.getTimestamp) else repr
|
||||
}
|
||||
|
||||
private def atomicWrite(atomicWrite: mf.AtomicWrite): AtomicWrite = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue