Skip to content

Commit

Permalink
GH-753 - Avoid superfluous, repeated deserialization in JdbcEventPubl…
Browse files Browse the repository at this point in the history
…ication.getEvent().
  • Loading branch information
odrotbohm committed Aug 7, 2024
1 parent 4802089 commit 9c7537f
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

Expand Down Expand Up @@ -369,7 +370,8 @@ private TargetEventPublication resultSetToPublication(ResultSet rs) throws SQLEx
var listenerId = rs.getString("LISTENER_ID");
var serializedEvent = rs.getString("SERIALIZED_EVENT");

return new JdbcEventPublication(id, publicationDate, listenerId, serializedEvent, eventClass, serializer,
return new JdbcEventPublication(id, publicationDate, listenerId,
() -> serializer.deserialize(serializedEvent, eventClass),
completionDate == null ? null : completionDate.toInstant());
}

Expand Down Expand Up @@ -414,11 +416,10 @@ private static class JdbcEventPublication implements TargetEventPublication {
private final UUID id;
private final Instant publicationDate;
private final String listenerId;
private final String serializedEvent;
private final Class<?> eventType;
private final Supplier<Object> eventSupplier;

private final EventSerializer serializer;
private @Nullable Instant completionDate;
private @Nullable Object event;

/**
* @param id must not be {@literal null}.
Expand All @@ -429,22 +430,17 @@ private static class JdbcEventPublication implements TargetEventPublication {
* @param serializer must not be {@literal null}.
* @param completionDate can be {@literal null}.
*/
public JdbcEventPublication(UUID id, Instant publicationDate, String listenerId, String serializedEvent,
Class<?> eventType, EventSerializer serializer, @Nullable Instant completionDate) {
public JdbcEventPublication(UUID id, Instant publicationDate, String listenerId, Supplier<Object> event,
@Nullable Instant completionDate) {

Assert.notNull(id, "Id must not be null!");
Assert.notNull(publicationDate, "Publication date must not be null!");
Assert.hasText(listenerId, "Listener id must not be null or empty!");
Assert.hasText(serializedEvent, "Serialized event must not be null or empty!");
Assert.notNull(eventType, "Event type must not be null!");
Assert.notNull(serializer, "EventSerializer must not be null!");

this.id = id;
this.publicationDate = publicationDate;
this.listenerId = listenerId;
this.serializedEvent = serializedEvent;
this.eventType = eventType;
this.serializer = serializer;
this.eventSupplier = event;
this.completionDate = completionDate;
}

Expand All @@ -462,8 +458,14 @@ public UUID getIdentifier() {
* @see org.springframework.modulith.events.EventPublication#getEvent()
*/
@Override
@SuppressWarnings("null")
public Object getEvent() {
return serializer.deserialize(serializedEvent, eventType);

if (event == null) {
this.event = eventSupplier.get();
}

return event;
}

/*
Expand Down Expand Up @@ -527,12 +529,10 @@ public boolean equals(@Nullable Object obj) {
}

return Objects.equals(completionDate, that.completionDate) //
&& Objects.equals(eventType, that.eventType) //
&& Objects.equals(id, that.id) //
&& Objects.equals(listenerId, that.listenerId) //
&& Objects.equals(publicationDate, that.publicationDate) //
&& Objects.equals(serializedEvent, that.serializedEvent) //
&& Objects.equals(serializer, that.serializer);
&& Objects.equals(getEvent(), that.getEvent());
}

/*
Expand All @@ -541,7 +541,7 @@ public boolean equals(@Nullable Object obj) {
*/
@Override
public int hashCode() {
return Objects.hash(completionDate, eventType, id, listenerId, publicationDate, serializedEvent, serializer);
return Objects.hash(completionDate, id, listenerId, publicationDate, getEvent());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,25 @@ void marksPublicationAsCompletedById() {
.containsExactly(publication.getIdentifier());
}

@Test // GH-753
void returnsSameEventInstanceFromPublication() {

// An event not implementing equals(…) / hashCode()
var event = new Sample();

// Serialize to whatever
doReturn("").when(serializer).serialize(event);

// Return fresh instances for every deserialization attempt
doAnswer(__ -> new Sample()).when(serializer).deserialize("", Sample.class);

repository.create(TargetEventPublication.of(event, TARGET_IDENTIFIER));

var publication = repository.findIncompletePublications().get(0);

assertThat(publication.getEvent()).isSameAs(publication.getEvent());
}

abstract String table();

private TargetEventPublication createPublication(Object event) {
Expand Down Expand Up @@ -422,4 +441,6 @@ class MysqlWithNoDefinedSchemaName extends WithNoDefinedSchemaName {}
private static final class TestEvent {
String eventId;
}

private static final class Sample {}
}

0 comments on commit 9c7537f

Please sign in to comment.