Avoid querying the database if we think all new messages are in the cache.

This commit is contained in:
Jon Chambers
2020-09-09 18:04:30 -04:00
committed by Jon Chambers
parent f766c57743
commit 6f9ff3be37
5 changed files with 103 additions and 26 deletions

View File

@@ -193,7 +193,7 @@ public class MessageController {
final OutgoingMessageEntityList outgoingMessages = messagesManager.getMessagesForDevice(account.getNumber(),
account.getUuid(),
account.getAuthenticatedDevice().get().getId(),
userAgent);
userAgent, false);
outgoingMessageListSizeHistogram.update(outgoingMessages.getMessages().size());

View File

@@ -11,6 +11,7 @@ import org.whispersystems.textsecuregcm.metrics.PushLatencyManager;
import org.whispersystems.textsecuregcm.redis.RedisOperation;
import org.whispersystems.textsecuregcm.util.Constants;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@@ -49,10 +50,10 @@ public class MessagesManager {
return messagesCache.takeEphemeralMessage(destinationUuid, destinationDevice);
}
public OutgoingMessageEntityList getMessagesForDevice(String destination, UUID destinationUuid, long destinationDevice, final String userAgent) {
public OutgoingMessageEntityList getMessagesForDevice(String destination, UUID destinationUuid, long destinationDevice, final String userAgent, final boolean cachedMessagesOnly) {
RedisOperation.unchecked(() -> pushLatencyManager.recordQueueRead(destinationUuid, destinationDevice, userAgent));
List<OutgoingMessageEntity> messages = this.messages.load(destination, destinationDevice);
List<OutgoingMessageEntity> messages = cachedMessagesOnly ? new ArrayList<>() : this.messages.load(destination, destinationDevice);
if (messages.size() <= Messages.RESULT_SET_CHUNK_SIZE) {
messages.addAll(messagesCache.get(destinationUuid, destinationDevice, Messages.RESULT_SET_CHUNK_SIZE - messages.size()));

View File

@@ -65,7 +65,9 @@ public class WebSocketConnection implements DispatchChannel, MessageAvailability
private final WebSocketClient client;
private final String connectionId;
private int storedMessageState = 0;
private int storedMessageState = 1;
private int lastPersistedState = 1;
private int lastDatabaseClearedState = 0;
private boolean processingStoredMessages = false;
private final AtomicBoolean sentInitialQueueEmptyMessage = new AtomicBoolean(false);
@@ -190,7 +192,8 @@ public class WebSocketConnection implements DispatchChannel, MessageAvailability
@VisibleForTesting
void processStoredMessages() {
final int processedState;
final int processedState;
final boolean cachedMessagesOnly;
synchronized (this) {
if (processingStoredMessages) {
@@ -199,9 +202,10 @@ public class WebSocketConnection implements DispatchChannel, MessageAvailability
processingStoredMessages = true;
processedState = storedMessageState;
cachedMessagesOnly = lastPersistedState <= lastDatabaseClearedState;
}
OutgoingMessageEntityList messages = messagesManager.getMessagesForDevice(account.getNumber(), account.getUuid(), device.getId(), client.getUserAgent());
OutgoingMessageEntityList messages = messagesManager.getMessagesForDevice(account.getNumber(), account.getUuid(), device.getId(), client.getUserAgent(), cachedMessagesOnly);
CompletableFuture<?>[] sendFutures = new CompletableFuture[messages.getMessages().size()];
for (int i = 0; i < messages.getMessages().size(); i++) {
@@ -232,14 +236,19 @@ public class WebSocketConnection implements DispatchChannel, MessageAvailability
}
CompletableFuture.allOf(sendFutures).whenComplete((v, cause) -> {
final boolean mayHaveMoreMessages;
synchronized (this) {
processingStoredMessages = false;
mayHaveMoreMessages = messages.hasMore() || storedMessageState > processedState;
}
if (messages.hasMore() || storedMessageState > processedState) {
if (mayHaveMoreMessages) {
processStoredMessages();
} else {
final boolean shouldSendEmptyQueueMessage;
synchronized (this) {
lastDatabaseClearedState = processedState;
}
if (sentInitialQueueEmptyMessage.compareAndSet(false, true)) {
client.sendRequest("PUT", "/api/v1/queue/empty", Collections.singletonList(TimestampHeaderUtil.getTimestampHeader()), Optional.empty());
@@ -267,6 +276,13 @@ public class WebSocketConnection implements DispatchChannel, MessageAvailability
@Override
public void handleMessagesPersisted() {
messagesPersistedMeter.mark();
synchronized (this) {
storedMessageState++;
lastPersistedState = storedMessageState;
}
processStoredMessages();
}
@Override