Skip to content

Commit

Permalink
Update build, match defaults with TS, fix custom events (#58)
Browse files Browse the repository at this point in the history
* Build updates

* Change default store activity interval to match TS

* Test custom payloads

* Add custom event handling

* Fix flaky tests
  • Loading branch information
wkal-pubnub authored Aug 22, 2024
1 parent 834b4eb commit b8ff729
Show file tree
Hide file tree
Showing 21 changed files with 386 additions and 191 deletions.
22 changes: 14 additions & 8 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,24 @@ import com.pubnub.gradle.tasks.GenerateVersionTask
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension

plugins {
kotlin("multiplatform") version "2.0.0" apply false
kotlin("plugin.serialization") version "2.0.0" apply false
kotlin("native.cocoapods") version "2.0.0" apply false
id("org.jlleitschuh.gradle.ktlint") version "12.1.0" apply false
id("org.jetbrains.kotlin.plugin.atomicfu") version "2.0.0"
id("com.vanniktech.maven.publish") version "0.29.0" apply false
id("org.jetbrains.dokka") version "1.9.20" apply false
alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.ktlint) apply false
alias(libs.plugins.benmanes.versions) apply false
alias(libs.plugins.vanniktech.maven.publish) apply false
alias(libs.plugins.dokka)
alias(libs.plugins.gradle.nexus.publish)
alias(libs.plugins.kotlinx.atomicfu)

id("pubnub.shared")
id("pubnub.dokka")
id("pubnub.multiplatform")
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.16.2"
alias(libs.plugins.kotlinx.compatibility.validator)
}

nexusPublishing {
repositories {
sonatype()
}
}

kotlin {
Expand Down
43 changes: 43 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[versions]
nexus = "2.0.0"
kotlin = "2.0.10"
vanniktech = "0.29.0"
ktlint = "12.1.0"
dokka = "1.9.20"
kotlinx_datetime = "0.6.0"
kotlinx_coroutines = "1.8.1"
kotlinx_serialization = "1.7.1"
pubnub = "9.2.0-DEV"

[libraries]
pubnub-core-api = { module = "com.pubnub:pubnub-core-api", version.ref = "pubnub" }
pubnub-kotlin-api = { module = "com.pubnub:pubnub-kotlin-api", version.ref = "pubnub" }
pubnub-kotlin-impl = { module = "com.pubnub:pubnub-kotlin-impl", version.ref = "pubnub" }
pubnub-kotlin = { module = "com.pubnub:pubnub-kotlin", version.ref = "pubnub" }
pubnub-kotlin-test = { module = "com.pubnub:pubnub-kotlin-test", version.ref = "pubnub" }
#slf4j = { module = "org.slf4j:slf4j-api", version = "1.7.36" }
#cbor = { module = "co.nstant.in:cbor", version = "0.9" }
#jetbrains-annotations = { module = "org.jetbrains:annotations", version = "24.1.0" }
kotlinx-atomicfu = { module = "org.jetbrains.kotlinx:atomicfu", version = "0.25.0" }
kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "kotlinx_serialization" }
benasher44-uuid = { module = "com.benasher44:uuid", version = "0.8.4" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx_datetime"}
lighthousegames-logging = { module = "org.lighthousegames:logging", version = "1.5.0"}

## tests
#logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
#logback-core = { module = "ch.qos.logback:logback-core", version.ref = "logback" }
#junit4 = { module = "junit:junit", version = "4.13.2" }
#coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx_coroutines"}
#
[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
kotlinx-atomicfu = { id = "org.jetbrains.kotlin.plugin.atomicfu", version.ref = "kotlin" }
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
benmanes-versions = { id = "com.github.ben-manes.versions", version = "0.42.0" }
vanniktech-maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "vanniktech" }
gradle-nexus-publish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexus" }
kotlinx-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version = "0.16.2" }
mokkery = { id = "dev.mokkery", version = "2.0.0" }
23 changes: 4 additions & 19 deletions pubnub-chat-api/api/pubnub-chat-api.api
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ public final class com/pubnub/chat/config/LogLevel : java/lang/Enum {

public final class com/pubnub/chat/config/PushNotificationsConfig {
public fun <init> (ZLjava/lang/String;Lcom/pubnub/api/enums/PNPushType;Ljava/lang/String;Lcom/pubnub/api/enums/PNPushEnvironment;)V
public synthetic fun <init> (ZLjava/lang/String;Lcom/pubnub/api/enums/PNPushType;Ljava/lang/String;Lcom/pubnub/api/enums/PNPushEnvironment;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getApnsEnvironment ()Lcom/pubnub/api/enums/PNPushEnvironment;
public final fun getApnsTopic ()Ljava/lang/String;
public final fun getDeviceGateway ()Lcom/pubnub/api/enums/PNPushType;
Expand Down Expand Up @@ -439,28 +440,12 @@ public final class com/pubnub/chat/types/EventContent$Companion {
}

public final class com/pubnub/chat/types/EventContent$Custom : com/pubnub/chat/types/EventContent {
public static final field Companion Lcom/pubnub/chat/types/EventContent$Custom$Companion;
public fun <init> (Ljava/lang/Object;Lcom/pubnub/chat/types/EmitEventMethod;)V
public synthetic fun <init> (Ljava/lang/Object;Lcom/pubnub/chat/types/EmitEventMethod;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getData ()Ljava/lang/Object;
public fun <init> (Ljava/util/Map;Lcom/pubnub/chat/types/EmitEventMethod;)V
public synthetic fun <init> (Ljava/util/Map;Lcom/pubnub/chat/types/EmitEventMethod;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getData ()Ljava/util/Map;
public final fun getMethod ()Lcom/pubnub/chat/types/EmitEventMethod;
}

public synthetic class com/pubnub/chat/types/EventContent$Custom$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lcom/pubnub/chat/types/EventContent$Custom$$serializer;
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/pubnub/chat/types/EventContent$Custom;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/pubnub/chat/types/EventContent$Custom;)V
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}

public final class com/pubnub/chat/types/EventContent$Custom$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class com/pubnub/chat/types/EventContent$Invite : com/pubnub/chat/types/EventContent {
public static final field Companion Lcom/pubnub/chat/types/EventContent$Invite$Companion;
public fun <init> (Lcom/pubnub/chat/types/ChannelType;Ljava/lang/String;)V
Expand Down
10 changes: 5 additions & 5 deletions pubnub-chat-api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
kotlin("plugin.serialization") version "2.0.0"
id("org.jetbrains.kotlin.plugin.atomicfu") version "2.0.0"
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.kotlinx.atomicfu)
id("pubnub.shared")
id("pubnub.dokka")
id("pubnub.multiplatform")
Expand All @@ -10,9 +10,9 @@ kotlin {
sourceSets {
val commonMain by getting {
dependencies {
api("com.pubnub:pubnub-core-api:9.2-DEV")
api("com.pubnub:pubnub-kotlin-api:9.2-DEV")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.0-RC")
api(libs.pubnub.core.api)
api(libs.pubnub.kotlin.api)
implementation(libs.kotlinx.serialization.core)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Chat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ interface Chat {
fun <T : EventContent> listenForEvents(
type: KClass<T>,
channelId: String,
customMethod: EmitEventMethod? = null,
customMethod: EmitEventMethod = EmitEventMethod.PUBLISH,
callback: (event: Event<T>) -> Unit
): AutoCloseable

Expand Down Expand Up @@ -194,7 +194,7 @@ interface Chat {

inline fun <reified T : EventContent> Chat.listenForEvents(
channelId: String,
customMethod: EmitEventMethod? = null,
customMethod: EmitEventMethod = EmitEventMethod.PUBLISH,
noinline callback: (event: Event<T>) -> Unit
): AutoCloseable {
return listenForEvents(T::class, channelId, customMethod, callback)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,22 @@ interface ChatConfiguration {
fun ChatConfiguration(
logLevel: LogLevel = LogLevel.OFF, // todo document all levels including "Off"
typingTimeout: Duration = 5.seconds,
storeUserActivityInterval: Duration = 60.seconds,
storeUserActivityInterval: Duration = 600.seconds,
storeUserActivityTimestamps: Boolean = false,
pushNotifications: PushNotificationsConfig = PushNotificationsConfig(
false,
null,
PNPushType.FCM,
null,
PNPushEnvironment.DEVELOPMENT
sendPushes = false,
deviceToken = null,
deviceGateway = PNPushType.FCM,
apnsTopic = null,
apnsEnvironment = PNPushEnvironment.DEVELOPMENT
),
rateLimitFactor: Int = 2,
rateLimitPerChannel: Map<ChannelType, Duration> = RateLimitPerChannel(),
customPayloads: CustomPayloads? = null,
): ChatConfiguration = object : ChatConfiguration {
override val logLevel: LogLevel = logLevel
override val typingTimeout: Duration = typingTimeout
override val storeUserActivityInterval: Duration = storeUserActivityInterval
override val storeUserActivityInterval: Duration = maxOf(storeUserActivityInterval, 60.seconds)
override val storeUserActivityTimestamps: Boolean = storeUserActivityTimestamps
override val pushNotifications: PushNotificationsConfig = pushNotifications
override val rateLimitFactor: Int = rateLimitFactor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.pubnub.api.JsonElement
import com.pubnub.chat.types.EventContent

class CustomPayloads(
val getMessagePublishBody: ((m: EventContent.TextMessageContent, channelId: String) -> Map<String, Any>)? = null,
val getMessagePublishBody: ((m: EventContent.TextMessageContent, channelId: String) -> Map<String, Any?>)? = null,
val getMessageResponseBody: (
(m: JsonElement) -> EventContent.TextMessageContent
)? = null, // todo do we have tests that checks this functionality
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ class PushNotificationsConfig(
val sendPushes: Boolean,
val deviceToken: String?,
val deviceGateway: PNPushType,
val apnsTopic: String?,
val apnsEnvironment: PNPushEnvironment
val apnsTopic: String? = null,
val apnsEnvironment: PNPushEnvironment = PNPushEnvironment.DEVELOPMENT
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.pubnub.chat.types

import com.pubnub.api.JsonElement
import com.pubnub.chat.restrictions.RestrictionType
import kotlinx.serialization.Contextual
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
Expand Down Expand Up @@ -44,10 +43,8 @@ sealed class EventContent {
@SerialName("invite")
class Invite(val channelType: ChannelType, val channelId: String) : EventContent()

@Serializable
@SerialName("custom")
class Custom(
@Contextual val data: Any,
val data: Map<String, Any?>,
@Transient val method: EmitEventMethod = EmitEventMethod.PUBLISH
) : EventContent()

Expand Down
24 changes: 12 additions & 12 deletions pubnub-chat-impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,40 @@ import com.pubnub.gradle.enableJsTarget
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension

plugins {
kotlin("plugin.serialization") version "2.0.0"
id("org.jetbrains.kotlin.plugin.atomicfu") version "2.0.0"
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.kotlinx.atomicfu)
id("pubnub.ios-simulator-test")
id("pubnub.shared")
id("pubnub.dokka")
id("pubnub.multiplatform")
id("dev.mokkery") version "2.0.0"
alias(libs.plugins.mokkery)
}

kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation("com.pubnub:pubnub-core-api:9.2-DEV")
implementation("com.pubnub:pubnub-kotlin-api:9.2-DEV")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.0-RC")
implementation("com.benasher44:uuid:0.8.4")
implementation("org.jetbrains.kotlinx:atomicfu:0.24.0")
implementation(project(":pubnub-chat-api"))
implementation("org.lighthousegames:logging:1.5.0")
implementation(libs.pubnub.core.api)
implementation(libs.pubnub.kotlin.api)
implementation(libs.kotlinx.datetime)
implementation(libs.kotlinx.serialization.core)
implementation(libs.kotlinx.atomicfu)
implementation(libs.benasher44.uuid)
implementation(libs.lighthousegames.logging)
}
}

val commonTest by getting {
dependencies {
implementation(kotlin("test"))
implementation("com.pubnub:pubnub-kotlin-test")
implementation(libs.pubnub.kotlin.test)
}
}

val jvmMain by getting {
dependencies {
implementation("com.pubnub:pubnub-kotlin:9.2-DEV")
implementation(libs.pubnub.kotlin)
implementation(kotlin("test-junit"))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package com.pubnub.chat.internal
import com.benasher44.uuid.uuid4
import com.pubnub.api.PubNub
import com.pubnub.api.PubNubException
import com.pubnub.api.asMap
import com.pubnub.api.asString
import com.pubnub.api.decode
import com.pubnub.api.enums.PNPushType
import com.pubnub.api.models.consumer.PNBoundedPage
import com.pubnub.api.models.consumer.PNPublishResult
Expand Down Expand Up @@ -580,15 +583,23 @@ class ChatImpl(
override fun <T : EventContent> listenForEvents(
type: KClass<T>,
channelId: String,
customMethod: EmitEventMethod?,
customMethod: EmitEventMethod,
callback: (event: Event<T>) -> Unit
): AutoCloseable {
val handler = fun(_: PubNub, pnEvent: PNEvent) {
if (pnEvent.channel != channelId) {
return
}
val message = (pnEvent as? MessageResult)?.message ?: return
val eventContent: EventContent = PNDataEncoder.decode<EventContent>(message)
val eventContent: EventContent = try {
PNDataEncoder.decode<EventContent>(message)
} catch (e: Exception) {
if (message.asMap()?.get("type")?.asString() == "custom") {
EventContent.Custom((message.decode() as Map<String, Any?>) - "type")
} else {
throw e
}
}

@Suppress("UNCHECKED_CAST")
val payload = eventContent as? T ?: return
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.pubnub.chat.internal

import com.pubnub.api.asMap
import com.pubnub.api.asString
import com.pubnub.api.decode
import com.pubnub.api.models.consumer.history.PNFetchMessageItem
import com.pubnub.chat.Chat
import com.pubnub.chat.Event
Expand All @@ -19,10 +22,19 @@ class EventImpl<T : EventContent>(
channelId: String,
pnFetchMessageItem: PNFetchMessageItem
): Event<EventContent> {
val eventContent: EventContent = try {
PNDataEncoder.decode<EventContent>(pnFetchMessageItem.message)
} catch (e: Exception) {
if (pnFetchMessageItem.message.asMap()?.get("type")?.asString() == "custom") {
EventContent.Custom((pnFetchMessageItem.message.decode() as Map<String, Any?>) - "type")
} else {
throw e
}
}
return EventImpl(
chat = chat,
timetoken = pnFetchMessageItem.timetoken ?: 0,
payload = PNDataEncoder.decode<EventContent>(pnFetchMessageItem.message),
payload = eventContent,
channelId = channelId,
userId = pnFetchMessageItem.uuid ?: "unknown-user"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,14 @@ data class MessageImpl(

companion object {
internal fun fromDTO(chat: ChatInternal, pnMessageResult: PNMessageResult): Message {
val content = chat.config.customPayloads?.getMessageResponseBody?.invoke(pnMessageResult.message) ?: defaultGetMessageResponseBody(pnMessageResult.message)
val content =
chat.config.customPayloads?.getMessageResponseBody?.invoke(pnMessageResult.message)
?: defaultGetMessageResponseBody(pnMessageResult.message)
?: EventContent.UnknownMessageFormat(pnMessageResult.message)
return MessageImpl(
chat,
pnMessageResult.timetoken!!,
content!!, // todo handle malformed content (then this is null)
content,
pnMessageResult.channel,
pnMessageResult.publisher!!,
meta = pnMessageResult.userMetadata?.decode() as? Map<String, Any>,
Expand All @@ -54,12 +57,15 @@ data class MessageImpl(
}

internal fun fromDTO(chat: ChatInternal, messageItem: PNFetchMessageItem, channelId: String): Message {
val content = chat.config.customPayloads?.getMessageResponseBody?.invoke(messageItem.message) ?: defaultGetMessageResponseBody(messageItem.message)
val content =
chat.config.customPayloads?.getMessageResponseBody?.invoke(messageItem.message)
?: defaultGetMessageResponseBody(messageItem.message)
?: EventContent.UnknownMessageFormat(messageItem.message)

return MessageImpl(
chat,
messageItem.timetoken!!,
content!!,
content,
channelId,
messageItem.uuid!!,
messageItem.actions,
Expand Down
Loading

0 comments on commit b8ff729

Please sign in to comment.