Adjust message queries for handshake sync

This causes problems with group messages as the received date is null
sometimes even though the status is RECEIVED.

The ReceivedMessageProcessor on the client filters out the synced
messages at the moment.
This commit is contained in:
2020-07-16 18:32:40 +02:00
parent 90662b3610
commit 43dfdc3334
7 changed files with 64 additions and 50 deletions

View File

@ -103,5 +103,5 @@ public abstract class Contact {
public void setCreationDate(Instant creationDate) { this.creationDate = creationDate; }
@Override
public String toString() { return String.format("%s[id=%d,name=%s, %d contact(s)]", getClass().getSimpleName(), id, name, contacts.size()); }
public String toString() { return String.format("%s[id=%d,name=%s,%d contact(s)]", getClass().getSimpleName(), id, name, contacts.size()); }
}

View File

@ -19,10 +19,10 @@ import envoy.data.Group;
@Entity
@NamedQuery(
name = GroupMessage.getPendingGroupMsg,
query = "SELECT m FROM GroupMessage m JOIN m.memberMessageStatus s WHERE (KEY(s) = :userId) AND ((m.creationDate > :lastSeen)"
+ "OR ((m.status = envoy.data.Message$MessageStatus.RECEIVED) AND (m.receivedDate > :lastSeen))"
+ "OR ((m.status = envoy.data.Message$MessageStatus.READ) AND (m.readDate > :lastSeen))"
+ "OR ((m.lastStatusChangeDate > :lastSeen)))"
query = "SELECT m FROM GroupMessage m JOIN m.memberMessageStatus s WHERE KEY(s) = :userId AND (m.creationDate > :lastSeen "
+ "OR m.status = envoy.data.Message$MessageStatus.RECEIVED AND m.receivedDate > :lastSeen "
+ "OR m.status = envoy.data.Message$MessageStatus.READ AND m.readDate > :lastSeen "
+ "OR m.lastStatusChangeDate > :lastSeen)"
)
public class GroupMessage extends Message {

View File

@ -12,11 +12,15 @@ import envoy.data.Message.MessageStatus;
import envoy.data.MessageBuilder;
/**
* This class serves as a way to let Hibernate communicate with the server
* without bringing the dependency of JPA/Hibernate into the client.<br>
* It will be referenced as "database message" to clarify between the different
* message objects.<br>
* <br>
* This JPA entity, which will be referred to as database message, stores the
* information contained inside a {@link envoy.data.Message} inside the
* database, while having a slightly different data layout.
* <p>
* A message can be converted to a database message by using the
* {@link Message#Message(envoy.data.Message)} constructor. A database message
* can be converted to a regular message using the {@link Message#toCommon()}
* method. In both cases, the objects will not contain references to each other.
* <p>
* Project: <strong>envoy-server-standalone</strong><br>
* File: <strong>Message.java</strong><br>
* Created: <strong>02.01.2020</strong><br>
@ -29,9 +33,14 @@ import envoy.data.MessageBuilder;
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@NamedQuery(
name = Message.getPending,
query = "SELECT m FROM Message m WHERE (m.recipient = :user AND m.status = envoy.data.Message$MessageStatus.SENT) "
+ "OR (m.sender = :user) AND ((m.status = envoy.data.Message$MessageStatus.RECEIVED) AND (m.receivedDate > :lastSeen)"
+ "OR (m.status = envoy.data.Message$MessageStatus.READ) AND (m.readDate > :lastSeen))"
query = "SELECT m FROM Message m WHERE "
// Send to or by the user before last seen
+ "(m.sender = :user OR m.recipient = :user) AND m.creationDate > :lastSeen "
// SENT to the user
+ "OR m.recipient = :user AND m.status = envoy.data.Message$MessageStatus.SENT "
// Sent by the user and RECEIVED / READ after last seen
+ "OR m.sender = :user AND (m.status = envoy.data.Message$MessageStatus.RECEIVED AND m.receivedDate > :lastSeen "
+ "OR m.status = envoy.data.Message$MessageStatus.READ AND m.readDate > :lastSeen)"
)
public class Message {
@ -107,17 +116,14 @@ public class Message {
* message
* @since Envoy Server Standalone v0.1-alpha
*/
public envoy.data.Message toCommon() {
return prepareBuilder().build();
}
public envoy.data.Message toCommon() { return prepareBuilder().build(); }
/**
* @return a message builder containing the state of this message
* @since Envoy Server Standalone v0.1-beta
*/
MessageBuilder prepareBuilder() {
var builder = new MessageBuilder(sender.getID(), recipient.getID(), id).setText(
text)
var builder = new MessageBuilder(sender.getID(), recipient.getID(), id).setText(text)
.setCreationDate(creationDate)
.setReceivedDate(receivedDate)
.setReadDate(readDate)

View File

@ -123,7 +123,11 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
for (var msg : pendingMessages) {
final var msgCommon = msg.toCommon();
if (msg.getStatus() == SENT) {
if (msg.getCreationDate().isAfter(credentials.getLastSync())) {
// Sync without side effects
writeProxy.write(socketID, msgCommon);
} else if (msg.getStatus() == SENT) {
// Send the message
writeProxy.write(socketID, msgCommon);
@ -146,34 +150,38 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
// Deliver the message to the user if he hasn't received it yet
if (gmsg.getMemberMessageStatus().get(user.getID()) == SENT) {
gmsg.getMemberMessageStatus().replace(user.getID(), RECEIVED);
if (gmsg.getMemberMessageStatus().replace(user.getID(), RECEIVED) != RECEIVED) {
gmsg.setLastStatusChangeDate(Instant.now());
gmsg.setLastStatusChangeDate(Instant.now());
writeProxy.write(socketID, gmsgCommon);
writeProxy.write(socketID, gmsgCommon);
// Notify all online group members about the status change
writeProxy.writeToOnlineContacts(gmsg.getRecipient().getContacts(),
new GroupMessageStatusChange(gmsg.getID(), RECEIVED, Instant
.now(),
connectionManager.getUserIDBySocketID(socketID)));
if (Collections.min(gmsg.getMemberMessageStatus().values()) == RECEIVED) {
gmsg.received();
// Notify online members about the status change
// Notify all online group members about the status change
writeProxy.writeToOnlineContacts(gmsg.getRecipient().getContacts(),
new MessageStatusChange(gmsg.getID(), gmsg.getStatus(), Instant.now()));
}
new GroupMessageStatusChange(gmsg.getID(), RECEIVED, Instant.now(), connectionManager.getUserIDBySocketID(socketID)));
PersistenceManager.getInstance().updateMessage(gmsg);
if (Collections.min(gmsg.getMemberMessageStatus().values()) == RECEIVED) {
gmsg.received();
// Notify online members about the status change
writeProxy.writeToOnlineContacts(gmsg.getRecipient().getContacts(),
new MessageStatusChange(gmsg.getID(), gmsg.getStatus(), Instant.now()));
}
PersistenceManager.getInstance().updateMessage(gmsg);
} else {
// Just send the message without updating if it was received in the past
writeProxy.write(socketID, gmsgCommon);
}
} else {
// Sending group message status changes
if (gmsg.getStatus() == SENT && gmsg.getLastStatusChangeDate().isAfter(gmsg.getCreationDate())
|| gmsg.getStatus() == RECEIVED && gmsg.getLastStatusChangeDate().isAfter(gmsg.getReceivedDate())) {
gmsg.getMemberMessageStatus().forEach((memberID, memberStatus) ->
writeProxy.write(socketID, new GroupMessageStatusChange(gmsg.getID(), memberStatus, gmsg.getLastStatusChangeDate(), memberID)));
gmsg.getMemberMessageStatus()
.forEach((memberID, memberStatus) -> writeProxy.write(socketID,
new GroupMessageStatusChange(gmsg.getID(), memberStatus, gmsg.getLastStatusChangeDate(), memberID)));
}
// Deliver just a status change instead of the whole message