From 275714cadc15b2f932275eac438831ed95ccfc50 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Tue, 18 Jul 2023 08:00:05 -0700 Subject: [PATCH] Paginate per batched query (#96) * add api client with grpc kotlin * take a pagination object so you can paginate per request * add more complex test for it * fix linter issue --- .../xmtp/android/library/ConversationTest.kt | 44 ++++++++++++++----- .../org/xmtp/android/library/TestHelpers.kt | 24 +++++++--- .../org/xmtp/android/library/Conversations.kt | 10 ++--- 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/library/src/androidTest/java/org/xmtp/android/library/ConversationTest.kt b/library/src/androidTest/java/org/xmtp/android/library/ConversationTest.kt index 715e0f5ac..f62e68c0f 100644 --- a/library/src/androidTest/java/org/xmtp/android/library/ConversationTest.kt +++ b/library/src/androidTest/java/org/xmtp/android/library/ConversationTest.kt @@ -20,6 +20,7 @@ import org.xmtp.android.library.messages.MessageBuilder import org.xmtp.android.library.messages.MessageHeaderV2Builder import org.xmtp.android.library.messages.MessageV1Builder import org.xmtp.android.library.messages.MessageV2Builder +import org.xmtp.android.library.messages.Pagination import org.xmtp.android.library.messages.PrivateKey import org.xmtp.android.library.messages.PrivateKeyBuilder import org.xmtp.android.library.messages.SealedInvitationBuilder @@ -419,27 +420,48 @@ class ConversationTest { @Test fun testListBatchMessages() { - val bobConversation = bobClient.conversations.newConversation( - alice.walletAddress, - context = InvitationV1ContextBuilder.buildFromConversation("hi") - ) + val bobConversation = aliceClient.conversations.newConversation(bob.walletAddress) + val steveConversation = aliceClient.conversations.newConversation(fixtures.steve.walletAddress) - val aliceConversation = aliceClient.conversations.newConversation( - bob.walletAddress, - context = InvitationV1ContextBuilder.buildFromConversation("hi") - ) bobConversation.send(text = "hey alice 1") bobConversation.send(text = "hey alice 2") - bobConversation.send(text = "hey alice 3") + steveConversation.send(text = "hey alice 3") val messages = aliceClient.conversations.listBatchMessages( listOf( - aliceConversation.topic, - bobConversation.topic + Pair(steveConversation.topic, null), + Pair(bobConversation.topic, null) ) ) assertEquals(3, messages.size) } + @Test + fun testListBatchMessagesWithPagination() { + val bobConversation = aliceClient.conversations.newConversation(bob.walletAddress) + val steveConversation = + aliceClient.conversations.newConversation(fixtures.steve.walletAddress) + + bobConversation.send(text = "hey alice 1 bob") + steveConversation.send(text = "hey alice 1 steve") + + Thread.sleep(100) + val date = Date() + + bobConversation.send(text = "hey alice 2 bob") + bobConversation.send(text = "hey alice 3 bob") + steveConversation.send(text = "hey alice 2 steve") + steveConversation.send(text = "hey alice 3 steve") + + val messages = aliceClient.conversations.listBatchMessages( + listOf( + Pair(steveConversation.topic, Pagination(after = date)), + Pair(bobConversation.topic, Pagination(after = date)) + ) + ) + + assertEquals(4, messages.size) + } + @Test fun testImportV1ConversationFromJS() { val jsExportJSONData = diff --git a/library/src/androidTest/java/org/xmtp/android/library/TestHelpers.kt b/library/src/androidTest/java/org/xmtp/android/library/TestHelpers.kt index 144e36d9b..533d6f09a 100644 --- a/library/src/androidTest/java/org/xmtp/android/library/TestHelpers.kt +++ b/library/src/androidTest/java/org/xmtp/android/library/TestHelpers.kt @@ -117,10 +117,12 @@ class FakeApiClient : ApiClient { } override suspend fun batchQuery(requests: List): MessageApiOuterClass.BatchQueryResponse { - val response = query(requests.first().getContentTopics(0)) + val responses = requests.map { + query(it.getContentTopics(0), Pagination(after = Date(it.startTimeNs))) + } return MessageApiOuterClass.BatchQueryResponse.newBuilder().also { - it.addResponses(response) + it.addAllResponses(responses) }.build() } @@ -142,12 +144,14 @@ class FakeApiClient : ApiClient { val startAt = pagination?.before if (startAt != null) { - result = result.filter { it.timestampNs < startAt.time * 1_000_000 } + result = result.filter { it.timestampNs < startAt.time } .sortedBy { it.timestampNs }.toMutableList() } val endAt = pagination?.after if (endAt != null) { - result = result.filter { it.timestampNs > endAt.time * 1_000_000 } + result = result.filter { + it.timestampNs > endAt.time + } .sortedBy { it.timestampNs }.toMutableList() } val limit = pagination?.limit @@ -187,7 +191,11 @@ class FakeApiClient : ApiClient { } } -data class Fixtures(val aliceAccount: PrivateKeyBuilder, val bobAccount: PrivateKeyBuilder, val steveAccount: PrivateKeyBuilder) { +data class Fixtures( + val aliceAccount: PrivateKeyBuilder, + val bobAccount: PrivateKeyBuilder, + val steveAccount: PrivateKeyBuilder, +) { var fakeApiClient: FakeApiClient = FakeApiClient() var alice: PrivateKey = aliceAccount.getPrivateKey() var aliceClient: Client = Client().create(account = aliceAccount, apiClient = fakeApiClient) @@ -196,7 +204,11 @@ data class Fixtures(val aliceAccount: PrivateKeyBuilder, val bobAccount: Private var steve: PrivateKey = steveAccount.getPrivateKey() var steveClient: Client = Client().create(account = steveAccount, apiClient = fakeApiClient) - constructor() : this(aliceAccount = PrivateKeyBuilder(), bobAccount = PrivateKeyBuilder(), steveAccount = PrivateKeyBuilder()) + constructor() : this( + aliceAccount = PrivateKeyBuilder(), + bobAccount = PrivateKeyBuilder(), + steveAccount = PrivateKeyBuilder() + ) fun publishLegacyContact(client: Client) { val contactBundle = ContactBundle.newBuilder().also { builder -> diff --git a/library/src/main/java/org/xmtp/android/library/Conversations.kt b/library/src/main/java/org/xmtp/android/library/Conversations.kt index 18898932e..fb2044ec3 100644 --- a/library/src/main/java/org/xmtp/android/library/Conversations.kt +++ b/library/src/main/java/org/xmtp/android/library/Conversations.kt @@ -285,14 +285,10 @@ data class Conversations( } fun listBatchMessages( - topics: List, - limit: Int? = null, - before: Date? = null, - after: Date? = null, + topics: List>, ): List { - val pagination = Pagination(limit = limit, before = before, after = after) - val requests = topics.map { topic -> - makeQueryRequest(topic = topic, pagination = pagination) + val requests = topics.map { (topic, page) -> + makeQueryRequest(topic = topic, pagination = page) } // The maximum number of requests permitted in a single batch call.