Skip to content

Commit

Permalink
Adjust membership to use partial updates from PubNub
Browse files Browse the repository at this point in the history
  • Loading branch information
wkal-pubnub committed Aug 8, 2024
1 parent 29d26a5 commit aaf6693
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 49 deletions.
5 changes: 4 additions & 1 deletion pubnub-chat-api/api/pubnub-chat-api.api
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public abstract interface class com/pubnub/chat/Channel {
public abstract fun getId ()Ljava/lang/String;
public abstract fun getMembers (Ljava/lang/Integer;Lcom/pubnub/api/models/consumer/objects/PNPage;Ljava/lang/String;Ljava/util/Collection;)Lcom/pubnub/kmp/PNFuture;
public abstract fun getMessage (J)Lcom/pubnub/kmp/PNFuture;
public abstract fun getMessageReportsHistory (Ljava/lang/Long;Ljava/lang/Long;I)Lcom/pubnub/kmp/PNFuture;
public abstract fun getName ()Ljava/lang/String;
public abstract fun getPinnedMessage ()Lcom/pubnub/kmp/PNFuture;
public abstract fun getStatus ()Ljava/lang/String;
Expand All @@ -33,6 +34,7 @@ public abstract interface class com/pubnub/chat/Channel {
public abstract fun setRestrictions (Lcom/pubnub/chat/User;ZZLjava/lang/String;)Lcom/pubnub/kmp/PNFuture;
public abstract fun startTyping ()Lcom/pubnub/kmp/PNFuture;
public abstract fun stopTyping ()Lcom/pubnub/kmp/PNFuture;
public abstract fun streamMessageReports (Lkotlin/jvm/functions/Function1;)Ljava/lang/AutoCloseable;
public abstract fun streamPresence (Lkotlin/jvm/functions/Function1;)Ljava/lang/AutoCloseable;
public abstract fun streamReadReceipts (Lkotlin/jvm/functions/Function1;)Ljava/lang/AutoCloseable;
public abstract fun streamUpdates (Lkotlin/jvm/functions/Function1;)Ljava/lang/AutoCloseable;
Expand All @@ -50,6 +52,7 @@ public final class com/pubnub/chat/Channel$DefaultImpls {
public static synthetic fun getFiles$default (Lcom/pubnub/chat/Channel;ILjava/lang/String;ILjava/lang/Object;)Lcom/pubnub/kmp/PNFuture;
public static synthetic fun getHistory$default (Lcom/pubnub/chat/Channel;Ljava/lang/Long;Ljava/lang/Long;IILjava/lang/Object;)Lcom/pubnub/kmp/PNFuture;
public static synthetic fun getMembers$default (Lcom/pubnub/chat/Channel;Ljava/lang/Integer;Lcom/pubnub/api/models/consumer/objects/PNPage;Ljava/lang/String;Ljava/util/Collection;ILjava/lang/Object;)Lcom/pubnub/kmp/PNFuture;
public static synthetic fun getMessageReportsHistory$default (Lcom/pubnub/chat/Channel;Ljava/lang/Long;Ljava/lang/Long;IILjava/lang/Object;)Lcom/pubnub/kmp/PNFuture;
public static synthetic fun getUserSuggestions$default (Lcom/pubnub/chat/Channel;Ljava/lang/String;IILjava/lang/Object;)Lcom/pubnub/kmp/PNFuture;
public static synthetic fun getUsersRestrictions$default (Lcom/pubnub/chat/Channel;Ljava/lang/Integer;Lcom/pubnub/api/models/consumer/objects/PNPage;Ljava/util/Collection;ILjava/lang/Object;)Lcom/pubnub/kmp/PNFuture;
public static synthetic fun join$default (Lcom/pubnub/chat/Channel;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/pubnub/kmp/PNFuture;
Expand Down Expand Up @@ -139,6 +142,7 @@ public abstract interface class com/pubnub/chat/Membership {
public abstract fun getUnreadMessagesCount ()Lcom/pubnub/kmp/PNFuture;
public abstract fun getUpdated ()Ljava/lang/String;
public abstract fun getUser ()Lcom/pubnub/chat/User;
public abstract fun plus (Lcom/pubnub/api/models/consumer/pubsub/objects/PNSetMembershipEvent;)Lcom/pubnub/chat/Membership;
public abstract fun setLastReadMessage (Lcom/pubnub/chat/Message;)Lcom/pubnub/kmp/PNFuture;
public abstract fun setLastReadMessageTimetoken (J)Lcom/pubnub/kmp/PNFuture;
public abstract fun streamUpdates (Lkotlin/jvm/functions/Function1;)Ljava/lang/AutoCloseable;
Expand Down Expand Up @@ -235,7 +239,6 @@ public abstract interface class com/pubnub/chat/User {
public abstract fun getUpdated ()Ljava/lang/String;
public abstract fun isPresentOn (Ljava/lang/String;)Lcom/pubnub/kmp/PNFuture;
public abstract fun plus (Lcom/pubnub/api/models/consumer/objects/uuid/PNUUIDMetadata;)Lcom/pubnub/chat/User;
public abstract fun report (Ljava/lang/String;)Lcom/pubnub/kmp/PNFuture;
public abstract fun setRestrictions (Lcom/pubnub/chat/Channel;ZZLjava/lang/String;)Lcom/pubnub/kmp/PNFuture;
public abstract fun streamUpdates (Lkotlin/jvm/functions/Function1;)Ljava/lang/AutoCloseable;
public abstract fun update (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)Lcom/pubnub/kmp/PNFuture;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.pubnub.chat

import com.pubnub.api.models.consumer.pubsub.objects.PNSetMembershipEvent
import com.pubnub.kmp.CustomObject
import com.pubnub.kmp.PNFuture

Expand All @@ -25,5 +26,7 @@ interface Membership {
// todo do we have test for this?
fun streamUpdates(callback: (membership: Membership?) -> Unit): AutoCloseable

operator fun plus(update: PNSetMembershipEvent): Membership

companion object
}
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ class ChatImpl(
override fun getThreadChannel(message: Message): PNFuture<ThreadChannel> {
val threadChannelId = getThreadId(message.channelId, message.timetoken)
return pubNub.getChannelMetadata(threadChannelId).then {
ThreadChannelImpl.fromDTO(this, message, it.data!!)
ThreadChannelImpl.fromDTO(this, message, it.data)
}.catch {
if (it is PubNubException && it.statusCode == HTTP_ERROR_404) {
Result.failure(PubNubException(THIS_MESSAGE_IS_NOT_A_THREAD, it))
Expand Down Expand Up @@ -1195,11 +1195,7 @@ class ChatImpl(
custom = createCustomObject(customWithUpdatedLastActiveTimestamp),
includeCustom = true,
).then { pnUUIDMetadataResult: PNUUIDMetadataResult ->
if (pnUUIDMetadataResult.data != null) {
currentUser = UserImpl.fromDTO(this, pnUUIDMetadataResult.data!!)
} else {
log.pnError(PNUUID_METADATA_IS_NULL)
}
currentUser = UserImpl.fromDTO(this, pnUUIDMetadataResult.data)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.pubnub.api.models.consumer.objects.member.PNMember
import com.pubnub.api.models.consumer.objects.membership.PNChannelDetailsLevel
import com.pubnub.api.models.consumer.objects.membership.PNChannelMembership
import com.pubnub.api.models.consumer.pubsub.objects.PNDeleteMembershipEventMessage
import com.pubnub.api.models.consumer.pubsub.objects.PNSetMembershipEvent
import com.pubnub.api.models.consumer.pubsub.objects.PNSetMembershipEventMessage
import com.pubnub.chat.Channel
import com.pubnub.chat.Membership
Expand Down Expand Up @@ -100,6 +101,17 @@ data class MembershipImpl(
}
}

override fun plus(update: PNSetMembershipEvent): Membership {
return MembershipImpl(
chat,
channel,
user,
update.custom?.value ?: custom,
update.updated,
update.eTag
)
}

private fun exists(): PNFuture<Boolean> =
chat.pubNub.getMemberships(uuid = user.id, filter = filterThisChannel()).then {
it.data.isNotEmpty()
Expand Down Expand Up @@ -128,20 +140,30 @@ data class MembershipImpl(
val membership = memberships.find { it.channel.id == event.channel && it.user.id == eventUuid }
?: return@createEventListener
val newMembership = when (val message = event.extractedMessage) {
is PNSetMembershipEventMessage -> MembershipImpl(
chat,
user = membership.user,
channel = membership.channel,
custom = message.data.custom,
updated = message.data.updated,
eTag = message.data.eTag
)
is PNSetMembershipEventMessage -> {
val previousMembership = latestMemberships.find { it.channel.id == event.channel && it.user.id == eventUuid }
previousMembership?.let { it + message.data }
?: MembershipImpl(
chat,
user = membership.user,
channel = membership.channel,
custom = message.data.custom?.value,
updated = message.data.updated,
eTag = message.data.eTag
)
}
is PNDeleteMembershipEventMessage -> null
else -> return@createEventListener
}
latestMemberships = latestMemberships.asSequence().filter {
it.channel.id != event.channel || it.user.id != eventUuid
}.run { newMembership?.let { plus(it) } ?: this }.toList()
latestMemberships = latestMemberships.asSequence().filter { membership ->
membership.channel.id != event.channel || membership.user.id != eventUuid
}.let { sequence ->
if (newMembership != null) {
sequence + newMembership
} else {
sequence
}
}.toList()
callback(latestMemberships)
})

Expand All @@ -154,9 +176,9 @@ data class MembershipImpl(
internal fun fromMembershipDTO(chat: ChatInternal, channelMembership: PNChannelMembership, user: User) =
MembershipImpl(
chat,
ChannelImpl.fromDTO(chat, channelMembership.channel!!),
ChannelImpl.fromDTO(chat, channelMembership.channel),
user,
channelMembership.custom,
channelMembership.custom?.value,
channelMembership.updated,
channelMembership.eTag
)
Expand All @@ -165,8 +187,8 @@ data class MembershipImpl(
MembershipImpl(
chat,
channel,
UserImpl.fromDTO(chat, userMembership.uuid!!),
userMembership.custom,
UserImpl.fromDTO(chat, userMembership.uuid),
userMembership.custom?.value,
userMembership.updated,
userMembership.eTag,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ data class ThreadChannelImpl(
log.pnError(PARENT_CHANNEL_DOES_NOT_EXISTS)
}
ChatImpl.pinMessageToChannel(chat.pubNub, message, parentChannel).then {
ChannelImpl.fromDTO(chat, it.data!!)
ChannelImpl.fromDTO(chat, it.data)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import com.pubnub.chat.internal.METADATA_REFERENCED_CHANNELS
import com.pubnub.chat.internal.METADATA_TEXT_LINKS
import com.pubnub.chat.internal.THREAD_ROOT_ID
import com.pubnub.chat.internal.channel.ChannelImpl
import com.pubnub.chat.internal.error.PubNubErrorMessage
import com.pubnub.chat.internal.error.PubNubErrorMessage.CANNOT_STREAM_MESSAGE_UPDATES_ON_EMPTY_LIST
import com.pubnub.chat.internal.serialization.PNDataEncoder
import com.pubnub.chat.internal.util.logErrorAndReturnException
import com.pubnub.chat.internal.util.pnError
import com.pubnub.chat.types.EventContent
import com.pubnub.chat.types.File
Expand Down Expand Up @@ -162,8 +164,11 @@ abstract class BaseMessage<T : Message>(

override fun pin(): PNFuture<Channel> {
return chat.getChannel(channelId).thenAsync { channel ->
ChatImpl.pinMessageToChannel(chat.pubNub, this, channel!!).then {
ChannelImpl.fromDTO(chat, it.data!!)
if (channel == null) {
throw log.logErrorAndReturnException(PubNubErrorMessage.CHANNEL_NOT_EXIST)
}
ChatImpl.pinMessageToChannel(chat.pubNub, this, channel).then {
ChannelImpl.fromDTO(chat, it.data)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ data class ThreadMessageImpl(
log.pnError(PARENT_CHANNEL_DOES_NOT_EXISTS)
}
ChatImpl.pinMessageToChannel(chat.pubNub, message, parentChannel).then {
ChannelImpl.fromDTO(chat, it.data!!)
ChannelImpl.fromDTO(chat, it.data)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ package com.pubnub.chat.internal.restrictions
import com.pubnub.api.models.consumer.objects.member.PNMember
import com.pubnub.api.models.consumer.objects.membership.PNChannelMembership
import com.pubnub.chat.internal.INTERNAL_MODERATION_PREFIX
import com.pubnub.chat.internal.error.PubNubErrorMessage.CHANNEL_ID_MUST_BE_DEFINED
import com.pubnub.chat.internal.error.PubNubErrorMessage.NO_SUCH_MEMBERSHIP_EXISTS
import com.pubnub.chat.internal.util.pnError
import com.pubnub.chat.restrictions.Restriction
import org.lighthousegames.logging.logging

Expand All @@ -15,12 +12,10 @@ class RestrictionImpl {

fun fromChannelMembershipDTO(userId: String, pnChannelMembership: PNChannelMembership): Restriction {
val channelId =
pnChannelMembership.channel?.id?.substringAfter(INTERNAL_MODERATION_PREFIX) ?: log.pnError(
CHANNEL_ID_MUST_BE_DEFINED
)
val customData: Map<String, Any?>? = pnChannelMembership.custom
val ban: Boolean = (customData?.get("ban") as? Boolean) ?: false
val mute: Boolean = (customData?.get("mute") as? Boolean) ?: false
pnChannelMembership.channel.id.substringAfter(INTERNAL_MODERATION_PREFIX)
val customData: Map<String, Any?>? = pnChannelMembership.custom?.value
val ban: Boolean = (customData?.get("ban") as? Boolean) == true
val mute: Boolean = (customData?.get("mute") as? Boolean) == true
val reason: String? = customData?.get("reason")?.toString()

return Restriction(
Expand All @@ -33,10 +28,10 @@ class RestrictionImpl {
}

fun fromMemberDTO(channelId: String, pnMember: PNMember): Restriction {
val userId = pnMember.uuid?.id ?: log.pnError(NO_SUCH_MEMBERSHIP_EXISTS)
val customData: Map<String, Any?>? = pnMember.custom
val ban: Boolean = (customData?.get("ban") as? Boolean) ?: false
val mute: Boolean = (customData?.get("mute") as? Boolean) ?: false
val userId = pnMember.uuid.id
val customData: Map<String, Any?>? = pnMember.custom?.value
val ban: Boolean = (customData?.get("ban") as? Boolean) == true
val mute: Boolean = (customData?.get("mute") as? Boolean) == true
val reason: String? = customData?.get("reason")?.toString()
return Restriction(
userId = userId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,16 @@ class MembershipIntegrationTest : BaseChatIntegrationTest() {
channel02.status
).await()
delayInMillis(1000)
val membership1 = channel01.join { }.await().also { it.disconnect?.close() }.membership
val membership2 = channel02.join { }.await().also { it.disconnect?.close() }.membership
val membership1 = channel01.join().await().membership
val membership2 = channel02.join().await().membership
delayInMillis(1000)

val expectedUpdates = listOf<List<Membership>>(
listOf(
membership1.asImpl().copy(custom = mapOf("a" to "b"), updated = null, eTag = null),
membership2.asImpl().copy(updated = null, eTag = null)
).sortedBy {
it.channel.id
},
listOf(membership1.asImpl().copy(custom = mapOf("a" to "b"), updated = null, eTag = null)).sortedBy { it.channel.id },
membership1.asImpl().copy(custom = mapOf("a" to "b")),
membership2.asImpl().copy()
),
listOf(membership1.asImpl().copy(custom = mapOf("a" to "b"))),
emptyList()
)
val actualUpdates = mutableListOf<List<Membership>>()
Expand All @@ -65,7 +63,14 @@ class MembershipIntegrationTest : BaseChatIntegrationTest() {
delayInMillis(1000)
dispose?.close()
}
assertEquals(expectedUpdates, actualUpdates)
assertEquals(
expectedUpdates.map { membershipList ->
membershipList.map { membership ->
membership.asImpl().copy(updated = null, eTag = null) as Membership
}.sortedBy { it.channel.id }
},
actualUpdates
)
}

@Test
Expand Down
2 changes: 1 addition & 1 deletion pubnub-kotlin
Submodule pubnub-kotlin updated 18 files
+4 −3 pubnub-core/pubnub-core-impl/src/main/kotlin/com/pubnub/internal/models/consumer/objects/member/PNMember.kt
+3 −2 ...nub-core-impl/src/main/kotlin/com/pubnub/internal/models/consumer/objects/membership/PNChannelMembership.kt
+1 −1 ...e/pubnub-core-impl/src/main/kotlin/com/pubnub/internal/models/consumer/objects/uuid/PNUUIDMetadataResult.kt
+3 −2 .../pubnub-core-impl/src/main/kotlin/com/pubnub/internal/models/consumer/pubsub/objects/PNObjectEventResult.kt
+12 −12 pubnub-core/pubnub-core-impl/src/test/kotlin/com/pubnub/contract/membership/step/WhenSteps.kt
+2 −2 pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/models/consumer/objects_api/member/PNMembers.java
+2 −2 ...-gson/pubnub-gson-api/src/main/java/com/pubnub/api/models/consumer/objects_api/membership/PNMembership.java
+2 −2 pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/v2/callbacks/DelegatingEventListener.java
+1 −1 pubnub-gson/pubnub-gson-impl/src/test/kotlin/com/pubnub/internal/v2/callbacks/DelegatingEventListenerTest.kt
+15 −3 ...ub-kotlin/pubnub-kotlin-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/objects/member/PNMember.kt
+28 −2 ...b-kotlin-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/objects/membership/PNChannelMembership.kt
+1 −1 ...pubnub-kotlin-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/objects/uuid/PNUUIDMetadataResult.kt
+3 −2 ...ubnub-kotlin-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/objects/PNObjectEventResult.kt
+39 −0 ...tlin-api/src/commonTest/kotlin/com/pubnub/api/models/consumer/objects/membership/PNChannelMembershipTest.kt
+5 −5 pubnub-kotlin/pubnub-kotlin-api/src/commonTest/kotlin/com/pubnub/test/integration/MembersTest.kt
+5 −5 pubnub-kotlin/pubnub-kotlin-api/src/commonTest/kotlin/com/pubnub/test/integration/MembershipsTest.kt
+12 −0 pubnub-kotlin/pubnub-kotlin-api/src/commonTest/kotlin/com/pubnub/test/integration/PushTest.kt
+5 −4 ...b-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/ObjectsIntegrationTest.kt

0 comments on commit aaf6693

Please sign in to comment.