Reduce database notifications for disappearing conversations.

This commit is contained in:
Greyson Parrelli 2020-06-07 14:46:03 -04:00
parent 8fe8a1e9ee
commit 3a479d7eef
4 changed files with 84 additions and 24 deletions

View file

@ -27,6 +27,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -46,6 +47,7 @@ public abstract class MessagingDatabase extends Database implements MmsSmsColumn
public abstract void markExpireStarted(long messageId); public abstract void markExpireStarted(long messageId);
public abstract void markExpireStarted(long messageId, long startTime); public abstract void markExpireStarted(long messageId, long startTime);
public abstract void markExpireStarted(Collection<Long> messageId, long startTime);
public abstract void markAsSent(long messageId, boolean secure); public abstract void markAsSent(long messageId, boolean secure);
public abstract void markUnidentified(long messageId, boolean unidentified); public abstract void markUnidentified(long messageId, boolean unidentified);

View file

@ -76,6 +76,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -570,19 +571,39 @@ public class MmsDatabase extends MessagingDatabase {
} }
@Override @Override
public void markExpireStarted(long messageId) { public void markExpireStarted(long id) {
markExpireStarted(messageId, System.currentTimeMillis()); markExpireStarted(id, System.currentTimeMillis());
} }
@Override @Override
public void markExpireStarted(long messageId, long startedTimestamp) { public void markExpireStarted(long id, long startedTimestamp) {
ContentValues contentValues = new ContentValues(); markExpireStarted(Collections.singleton(id), startedTimestamp);
contentValues.put(EXPIRE_STARTED, startedTimestamp); }
SQLiteDatabase db = databaseHelper.getWritableDatabase(); @Override
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {String.valueOf(messageId)}); public void markExpireStarted(Collection<Long> ids, long startedAtTimestamp) {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
long threadId = -1;
long threadId = getThreadIdForMessage(messageId); db.beginTransaction();
try {
for (long id : ids) {
ContentValues contentValues = new ContentValues();
contentValues.put(EXPIRE_STARTED, startedAtTimestamp);
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[]{String.valueOf(id)});
if (threadId < 0) {
threadId = getThreadIdForMessage(id);
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
DatabaseFactory.getThreadDatabase(context).update(threadId, false);
notifyConversationListeners(threadId); notifyConversationListeners(threadId);
} }

View file

@ -51,6 +51,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
import java.io.IOException; import java.io.IOException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -355,13 +356,31 @@ public class SmsDatabase extends MessagingDatabase {
@Override @Override
public void markExpireStarted(long id, long startedAtTimestamp) { public void markExpireStarted(long id, long startedAtTimestamp) {
ContentValues contentValues = new ContentValues(); markExpireStarted(Collections.singleton(id), startedAtTimestamp);
contentValues.put(EXPIRE_STARTED, startedAtTimestamp); }
SQLiteDatabase db = databaseHelper.getWritableDatabase(); @Override
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {String.valueOf(id)}); public void markExpireStarted(Collection<Long> ids, long startedAtTimestamp) {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
long threadId = -1;
long threadId = getThreadIdForMessage(id); db.beginTransaction();
try {
for (long id : ids) {
ContentValues contentValues = new ContentValues();
contentValues.put(EXPIRE_STARTED, startedAtTimestamp);
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[]{String.valueOf(id)});
if (threadId < 0) {
threadId = getThreadIdForMessage(id);
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
DatabaseFactory.getThreadDatabase(context).update(threadId, false); DatabaseFactory.getThreadDatabase(context).update(threadId, false);
notifyConversationListeners(threadId); notifyConversationListeners(threadId);

View file

@ -70,12 +70,21 @@ public class MarkReadReceiver extends BroadcastReceiver {
public static void process(@NonNull Context context, @NonNull List<MarkedMessageInfo> markedReadMessages) { public static void process(@NonNull Context context, @NonNull List<MarkedMessageInfo> markedReadMessages) {
if (markedReadMessages.isEmpty()) return; if (markedReadMessages.isEmpty()) return;
List<SyncMessageId> syncMessageIds = new LinkedList<>(); List<SyncMessageId> syncMessageIds = Stream.of(markedReadMessages)
.map(MarkedMessageInfo::getSyncMessageId)
.toList();
List<ExpirationInfo> mmsExpirationInfo = Stream.of(markedReadMessages)
.map(MarkedMessageInfo::getExpirationInfo)
.filter(ExpirationInfo::isMms)
.filter(info -> info.getExpiresIn() > 0 && info.getExpireStarted() <= 0)
.toList();
List<ExpirationInfo> smsExpirationInfo = Stream.of(markedReadMessages)
.map(MarkedMessageInfo::getExpirationInfo)
.filterNot(ExpirationInfo::isMms)
.filter(info -> info.getExpiresIn() > 0 && info.getExpireStarted() <= 0)
.toList();
for (MarkedMessageInfo messageInfo : markedReadMessages) { scheduleDeletion(context, smsExpirationInfo, mmsExpirationInfo);
scheduleDeletion(context, messageInfo.getExpirationInfo());
syncMessageIds.add(messageInfo.getSyncMessageId());
}
ApplicationDependencies.getJobManager().add(new MultiDeviceReadUpdateJob(syncMessageIds)); ApplicationDependencies.getJobManager().add(new MultiDeviceReadUpdateJob(syncMessageIds));
@ -95,14 +104,23 @@ public class MarkReadReceiver extends BroadcastReceiver {
}); });
} }
private static void scheduleDeletion(Context context, ExpirationInfo expirationInfo) { private static void scheduleDeletion(@NonNull Context context,
if (expirationInfo.getExpiresIn() > 0 && expirationInfo.getExpireStarted() <= 0) { @NonNull List<ExpirationInfo> smsExpirationInfo,
@NonNull List<ExpirationInfo> mmsExpirationInfo)
{
if (smsExpirationInfo.size() > 0) {
DatabaseFactory.getSmsDatabase(context).markExpireStarted(Stream.of(smsExpirationInfo).map(ExpirationInfo::getId).toList(), System.currentTimeMillis());
}
if (mmsExpirationInfo.size() > 0) {
DatabaseFactory.getMmsDatabase(context).markExpireStarted(Stream.of(mmsExpirationInfo).map(ExpirationInfo::getId).toList(), System.currentTimeMillis());
}
if (smsExpirationInfo.size() + mmsExpirationInfo.size() > 0) {
ExpiringMessageManager expirationManager = ApplicationContext.getInstance(context).getExpiringMessageManager(); ExpiringMessageManager expirationManager = ApplicationContext.getInstance(context).getExpiringMessageManager();
if (expirationInfo.isMms()) DatabaseFactory.getMmsDatabase(context).markExpireStarted(expirationInfo.getId()); Stream.concat(Stream.of(smsExpirationInfo), Stream.of(mmsExpirationInfo))
else DatabaseFactory.getSmsDatabase(context).markExpireStarted(expirationInfo.getId()); .forEach(info -> expirationManager.scheduleDeletion(info.getId(), info.isMms(), info.getExpiresIn()));
expirationManager.scheduleDeletion(expirationInfo.getId(), expirationInfo.isMms(), expirationInfo.getExpiresIn());
} }
} }
} }