mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-20 04:48:04 +01:00
Optimize message deletion by skipping lookup
This commit is contained in:
@@ -544,7 +544,8 @@ public class MessageController {
|
||||
Optional<OutgoingMessageEntity> message = messagesManager.delete(
|
||||
auth.getAccount().getUuid(),
|
||||
auth.getAuthenticatedDevice().getId(),
|
||||
uuid);
|
||||
uuid,
|
||||
null);
|
||||
|
||||
if (message.isPresent()) {
|
||||
WebSocketConnection.recordMessageDeliveryDuration(message.get().getTimestamp(), auth.getAuthenticatedDevice());
|
||||
|
||||
@@ -52,6 +52,7 @@ public class MessagesDynamoDb extends AbstractDynamoDbStore {
|
||||
private final Timer storeTimer = timer(name(getClass(), "store"));
|
||||
private final Timer loadTimer = timer(name(getClass(), "load"));
|
||||
private final Timer deleteByGuid = timer(name(getClass(), "delete", "guid"));
|
||||
private final Timer deleteByKey = timer(name(getClass(), "delete", "key"));
|
||||
private final Timer deleteByAccount = timer(name(getClass(), "delete", "account"));
|
||||
private final Timer deleteByDevice = timer(name(getClass(), "delete", "device"));
|
||||
|
||||
@@ -158,6 +159,24 @@ public class MessagesDynamoDb extends AbstractDynamoDbStore {
|
||||
});
|
||||
}
|
||||
|
||||
public Optional<OutgoingMessageEntity> deleteMessage(final UUID destinationAccountUuid,
|
||||
final long destinationDeviceId, final UUID messageUuid, final long serverTimestamp) {
|
||||
return deleteByKey.record(() -> {
|
||||
final AttributeValue partitionKey = convertPartitionKey(destinationAccountUuid);
|
||||
final AttributeValue sortKey = convertSortKey(destinationDeviceId, serverTimestamp, messageUuid);
|
||||
DeleteItemRequest.Builder deleteItemRequest = DeleteItemRequest.builder()
|
||||
.tableName(tableName)
|
||||
.key(Map.of(KEY_PARTITION, partitionKey, KEY_SORT, sortKey))
|
||||
.returnValues(ReturnValue.ALL_OLD);
|
||||
final DeleteItemResponse deleteItemResponse = db().deleteItem(deleteItemRequest.build());
|
||||
if (deleteItemResponse.attributes() != null && deleteItemResponse.attributes().containsKey(KEY_PARTITION)) {
|
||||
return Optional.of(convertItemToOutgoingMessageEntity(deleteItemResponse.attributes()));
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
});
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Optional<OutgoingMessageEntity> deleteItemsMatchingQueryAndReturnFirstOneActuallyDeleted(AttributeValue partitionKey, QueryRequest queryRequest) {
|
||||
Optional<OutgoingMessageEntity> result = Optional.empty();
|
||||
|
||||
@@ -91,11 +91,15 @@ public class MessagesManager {
|
||||
messagesDynamoDb.deleteAllMessagesForDevice(destinationUuid, deviceId);
|
||||
}
|
||||
|
||||
public Optional<OutgoingMessageEntity> delete(UUID destinationUuid, long destinationDeviceId, UUID guid) {
|
||||
public Optional<OutgoingMessageEntity> delete(UUID destinationUuid, long destinationDeviceId, UUID guid, Long serverTimestamp) {
|
||||
Optional<OutgoingMessageEntity> removed = messagesCache.remove(destinationUuid, destinationDeviceId, guid);
|
||||
|
||||
if (removed.isEmpty()) {
|
||||
removed = messagesDynamoDb.deleteMessageByDestinationAndGuid(destinationUuid, guid);
|
||||
if (serverTimestamp == null) {
|
||||
removed = messagesDynamoDb.deleteMessageByDestinationAndGuid(destinationUuid, guid);
|
||||
} else {
|
||||
removed = messagesDynamoDb.deleteMessage(destinationUuid, destinationDeviceId, guid, serverTimestamp);
|
||||
}
|
||||
cacheMissByGuidMeter.mark();
|
||||
} else {
|
||||
cacheHitByGuidMeter.mark();
|
||||
|
||||
@@ -194,7 +194,7 @@ public class WebSocketConnection implements MessageAvailabilityListener, Displac
|
||||
if (throwable == null) {
|
||||
if (isSuccessResponse(response)) {
|
||||
if (storedMessageInfo.isPresent()) {
|
||||
messagesManager.delete(auth.getAccount().getUuid(), device.getId(), storedMessageInfo.get().getGuid());
|
||||
messagesManager.delete(auth.getAccount().getUuid(), device.getId(), storedMessageInfo.get().getGuid(), storedMessageInfo.get().getServerTimestamp());
|
||||
}
|
||||
|
||||
if (message.getType() != Envelope.Type.SERVER_DELIVERY_RECEIPT) {
|
||||
@@ -337,12 +337,12 @@ public class WebSocketConnection implements MessageAvailabilityListener, Displac
|
||||
final Envelope envelope = builder.build();
|
||||
|
||||
if (envelope.getSerializedSize() > MAX_DESKTOP_MESSAGE_SIZE && isDesktopClient) {
|
||||
messagesManager.delete(auth.getAccount().getUuid(), device.getId(), message.getGuid());
|
||||
messagesManager.delete(auth.getAccount().getUuid(), device.getId(), message.getGuid(), message.getServerTimestamp());
|
||||
discardedMessagesMeter.mark();
|
||||
|
||||
sendFutures[i] = CompletableFuture.completedFuture(null);
|
||||
} else {
|
||||
sendFutures[i] = sendMessage(builder.build(), Optional.of(new StoredMessageInfo(message.getGuid())));
|
||||
sendFutures[i] = sendMessage(builder.build(), Optional.of(new StoredMessageInfo(message.getGuid(), message.getServerTimestamp())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,13 +396,19 @@ public class WebSocketConnection implements MessageAvailabilityListener, Displac
|
||||
|
||||
private static class StoredMessageInfo {
|
||||
private final UUID guid;
|
||||
private final long serverTimestamp;
|
||||
|
||||
public StoredMessageInfo(UUID guid) {
|
||||
public StoredMessageInfo(UUID guid, long serverTimestamp) {
|
||||
this.guid = guid;
|
||||
this.serverTimestamp = serverTimestamp;
|
||||
}
|
||||
|
||||
public UUID getGuid() {
|
||||
return guid;
|
||||
}
|
||||
|
||||
public long getServerTimestamp() {
|
||||
return serverTimestamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user