Fix hot loop when trying to delete stories but only onboarding exists.

fork-5.53.8
Alex Hart 2022-07-13 14:52:32 -03:00 zatwierdzone przez Cody Henthorne
rodzic 15111b2792
commit 2f17963b2b
5 zmienionych plików z 73 dodań i 12 usunięć

Wyświetl plik

@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.database
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@ -18,6 +19,7 @@ import org.whispersystems.signalservice.api.push.ACI
import org.whispersystems.signalservice.api.push.PNI import org.whispersystems.signalservice.api.push.PNI
import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.ServiceId
import java.util.UUID import java.util.UUID
import java.util.concurrent.TimeUnit
@Suppress("ClassName") @Suppress("ClassName")
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
@ -30,6 +32,7 @@ class MmsDatabaseTest_stories {
private lateinit var myStory: Recipient private lateinit var myStory: Recipient
private lateinit var recipients: List<RecipientId> private lateinit var recipients: List<RecipientId>
private lateinit var releaseChannelRecipient: Recipient
@Before @Before
fun setUp() { fun setUp() {
@ -42,6 +45,9 @@ class MmsDatabaseTest_stories {
myStory = Recipient.resolved(SignalDatabase.recipients.getOrInsertFromDistributionListId(DistributionListId.MY_STORY)) myStory = Recipient.resolved(SignalDatabase.recipients.getOrInsertFromDistributionListId(DistributionListId.MY_STORY))
recipients = (0 until 5).map { SignalDatabase.recipients.getOrInsertFromServiceId(ServiceId.from(UUID.randomUUID())) } recipients = (0 until 5).map { SignalDatabase.recipients.getOrInsertFromServiceId(ServiceId.from(UUID.randomUUID())) }
releaseChannelRecipient = Recipient.resolved(SignalDatabase.recipients.insertReleaseChannelRecipient())
SignalStore.releaseChannelValues().setReleaseChannelRecipientId(releaseChannelRecipient.id)
} }
@Test @Test
@ -333,4 +339,41 @@ class MmsDatabaseTest_stories {
// THEN // THEN
assertFalse(result) assertFalse(result)
} }
@Test
fun givenNotViewedOnboardingAndOnlyStoryIsOnboardingAndAdded2DaysAgo_whenIGetOldestStoryTimestamp_thenIExpectNull() {
// GIVEN
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(releaseChannelRecipient)
MmsHelper.insert(
recipient = releaseChannelRecipient,
sentTimeMillis = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(2),
storyType = StoryType.STORY_WITH_REPLIES,
threadId = threadId
)
// WHEN
val oldestTimestamp = SignalDatabase.mms.getOldestStorySendTimestamp(false)
// THEN
assertNull(oldestTimestamp)
}
@Test
fun givenViewedOnboardingAndOnlyStoryIsOnboardingAndAdded2DaysAgo_whenIGetOldestStoryTimestamp_thenIExpectNotNull() {
// GIVEN
val expected = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(2)
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(releaseChannelRecipient)
MmsHelper.insert(
recipient = releaseChannelRecipient,
sentTimeMillis = expected,
storyType = StoryType.STORY_WITH_REPLIES,
threadId = threadId
)
// WHEN
val oldestTimestamp = SignalDatabase.mms.getOldestStorySendTimestamp(true)
// THEN
assertEquals(expected, oldestTimestamp)
}
} }

Wyświetl plik

@ -200,7 +200,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
public abstract boolean hasSelfReplyInStory(long parentStoryId); public abstract boolean hasSelfReplyInStory(long parentStoryId);
public abstract boolean hasSelfReplyInGroupStory(long parentStoryId); public abstract boolean hasSelfReplyInGroupStory(long parentStoryId);
public abstract @NonNull Cursor getStoryReplies(long parentStoryId); public abstract @NonNull Cursor getStoryReplies(long parentStoryId);
public abstract @Nullable Long getOldestStorySendTimestamp(); public abstract @Nullable Long getOldestStorySendTimestamp(boolean hasSeenReleaseChannelStories);
public abstract int deleteStoriesOlderThan(long timestamp, boolean hasSeenReleaseChannelStories); public abstract int deleteStoriesOlderThan(long timestamp, boolean hasSeenReleaseChannelStories);
public abstract @NonNull MessageDatabase.Reader getUnreadStories(@NonNull RecipientId recipientId, int limit); public abstract @NonNull MessageDatabase.Reader getUnreadStories(@NonNull RecipientId recipientId, int limit);
public abstract @Nullable ParentStoryId.GroupReply getParentStoryIdForGroupReply(long messageId); public abstract @Nullable ParentStoryId.GroupReply getParentStoryIdForGroupReply(long messageId);

Wyświetl plik

@ -898,18 +898,37 @@ public class MmsDatabase extends MessageDatabase {
} }
@Override @Override
public @Nullable Long getOldestStorySendTimestamp() { public @Nullable Long getOldestStorySendTimestamp(boolean hasSeenReleaseChannelStories) {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase(); long releaseChannelThreadId = getReleaseChannelThreadId(hasSeenReleaseChannelStories);
String[] columns = new String[]{DATE_SENT}; SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
String where = IS_STORY_CLAUSE; String[] columns = new String[] { DATE_SENT };
String orderBy = DATE_SENT + " ASC"; String where = IS_STORY_CLAUSE + " AND " + THREAD_ID + " != ?";
String limit = "1"; String orderBy = DATE_SENT + " ASC";
String limit = "1";
try (Cursor cursor = db.query(TABLE_NAME, columns, where, null, null, null, orderBy, limit)) { try (Cursor cursor = db.query(TABLE_NAME, columns, where, SqlUtil.buildArgs(releaseChannelThreadId), null, null, orderBy, limit)) {
return cursor != null && cursor.moveToNext() ? cursor.getLong(0) : null; return cursor != null && cursor.moveToNext() ? cursor.getLong(0) : null;
} }
} }
private static long getReleaseChannelThreadId(boolean hasSeenReleaseChannelStories) {
if (hasSeenReleaseChannelStories) {
return -1L;
}
RecipientId releaseChannelRecipientId = SignalStore.releaseChannelValues().getReleaseChannelRecipientId();
if (releaseChannelRecipientId == null) {
return -1L;
}
Long releaseChannelThreadId = SignalDatabase.threads().getThreadIdFor(releaseChannelRecipientId);
if (releaseChannelThreadId == null) {
return -1L;
}
return releaseChannelThreadId;
}
@Override @Override
public void deleteGroupStoryReplies(long parentStoryId) { public void deleteGroupStoryReplies(long parentStoryId) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
@ -924,8 +943,7 @@ public class MmsDatabase extends MessageDatabase {
db.beginTransaction(); db.beginTransaction();
try { try {
RecipientId releaseChannelRecipient = hasSeenReleaseChannelStories ? null : SignalStore.releaseChannelValues().getReleaseChannelRecipientId(); long releaseChannelThreadId = getReleaseChannelThreadId(hasSeenReleaseChannelStories);
long releaseChannelThreadId = releaseChannelRecipient != null ? SignalDatabase.threads().getOrCreateThreadIdFor(Recipient.resolved(releaseChannelRecipient)) : -1;
String storiesBeforeTimestampWhere = IS_STORY_CLAUSE + " AND " + DATE_SENT + " < ? AND " + THREAD_ID + " != ?"; String storiesBeforeTimestampWhere = IS_STORY_CLAUSE + " AND " + DATE_SENT + " < ? AND " + THREAD_ID + " != ?";
String[] sharedArgs = SqlUtil.buildArgs(timestamp, releaseChannelThreadId); String[] sharedArgs = SqlUtil.buildArgs(timestamp, releaseChannelThreadId);
String deleteStoryRepliesQuery = "DELETE FROM " + TABLE_NAME + " " + String deleteStoryRepliesQuery = "DELETE FROM " + TABLE_NAME + " " +

Wyświetl plik

@ -1462,7 +1462,7 @@ public class SmsDatabase extends MessageDatabase {
} }
@Override @Override
public @Nullable Long getOldestStorySendTimestamp() { public @Nullable Long getOldestStorySendTimestamp(boolean hasSeenReleaseChannelStories) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

Wyświetl plik

@ -32,7 +32,7 @@ class ExpiringStoriesManager(
@WorkerThread @WorkerThread
override fun getNextClosestEvent(): Event? { override fun getNextClosestEvent(): Event? {
val oldestTimestamp = mmsDatabase.oldestStorySendTimestamp ?: return null val oldestTimestamp = mmsDatabase.getOldestStorySendTimestamp(SignalStore.storyValues().userHasSeenOnboardingStory) ?: return null
val timeSinceSend = System.currentTimeMillis() - oldestTimestamp val timeSinceSend = System.currentTimeMillis() - oldestTimestamp
val delay = (STORY_LIFESPAN - timeSinceSend).coerceAtLeast(0) val delay = (STORY_LIFESPAN - timeSinceSend).coerceAtLeast(0)