diff --git a/chat-android/src/main/java/com/ably/chat/Discontinuities.kt b/chat-android/src/main/java/com/ably/chat/Discontinuities.kt index 61048411..f9ac6cff 100644 --- a/chat-android/src/main/java/com/ably/chat/Discontinuities.kt +++ b/chat-android/src/main/java/com/ably/chat/Discontinuities.kt @@ -2,7 +2,6 @@ package com.ably.chat import io.ably.lib.types.ErrorInfo import io.ably.lib.util.EventEmitter -import io.ably.lib.util.Log import io.ably.lib.realtime.ChannelBase as AblyRealtimeChannel /** @@ -44,12 +43,15 @@ interface EmitsDiscontinuities { } } -class DiscontinuityEmitter : EventEmitter() { +internal class DiscontinuityEmitter(logger: Logger) : EventEmitter() { + private val logger = logger.withContext("DiscontinuityEmitter") + override fun apply(listener: EmitsDiscontinuities.Listener?, event: String?, vararg args: Any?) { try { - listener?.discontinuityEmitted(args[0] as? ErrorInfo?) + val reason = args.firstOrNull() as? ErrorInfo? + listener?.discontinuityEmitted(reason) } catch (t: Throwable) { - Log.e("DiscontinuityEmitter", "Unexpected exception calling Discontinuity Listener", t) + logger.error("Unexpected exception calling Discontinuity Listener", t) } } } diff --git a/chat-android/src/main/java/com/ably/chat/Messages.kt b/chat-android/src/main/java/com/ably/chat/Messages.kt index 17d316e1..90f9b93c 100644 --- a/chat-android/src/main/java/com/ably/chat/Messages.kt +++ b/chat-android/src/main/java/com/ably/chat/Messages.kt @@ -225,7 +225,8 @@ internal class DefaultMessages( private val roomId: String, private val realtimeChannels: AblyRealtime.Channels, private val chatApi: ChatApi, -) : Messages, ContributesToRoomLifecycleImpl() { + private val logger: Logger, +) : Messages, ContributesToRoomLifecycleImpl(logger) { override val featureName: String = "messages" diff --git a/chat-android/src/main/java/com/ably/chat/Occupancy.kt b/chat-android/src/main/java/com/ably/chat/Occupancy.kt index 4f5978f4..f8c68876 100644 --- a/chat-android/src/main/java/com/ably/chat/Occupancy.kt +++ b/chat-android/src/main/java/com/ably/chat/Occupancy.kt @@ -77,7 +77,7 @@ internal class DefaultOccupancy( private val chatApi: ChatApi, private val roomId: String, private val logger: Logger, -) : Occupancy, ContributesToRoomLifecycleImpl() { +) : Occupancy, ContributesToRoomLifecycleImpl(logger) { override val featureName: String = "occupancy" diff --git a/chat-android/src/main/java/com/ably/chat/Presence.kt b/chat-android/src/main/java/com/ably/chat/Presence.kt index 110ae8b0..278a8a37 100644 --- a/chat-android/src/main/java/com/ably/chat/Presence.kt +++ b/chat-android/src/main/java/com/ably/chat/Presence.kt @@ -137,7 +137,8 @@ internal class DefaultPresence( private val clientId: String, override val channel: Channel, private val presence: PubSubPresence, -) : Presence, ContributesToRoomLifecycleImpl() { + private val logger: Logger, +) : Presence, ContributesToRoomLifecycleImpl(logger) { override val featureName = "presence" diff --git a/chat-android/src/main/java/com/ably/chat/Room.kt b/chat-android/src/main/java/com/ably/chat/Room.kt index 9505eba8..c4996759 100644 --- a/chat-android/src/main/java/com/ably/chat/Room.kt +++ b/chat-android/src/main/java/com/ably/chat/Room.kt @@ -128,6 +128,7 @@ internal class DefaultRoom( roomId = roomId, realtimeChannels = realtimeClient.channels, chatApi = chatApi, + logger = logger.withContext(tag = "Messages"), ) private var _presence: Presence? = null @@ -186,6 +187,7 @@ internal class DefaultRoom( clientId = clientId, channel = messages.channel, presence = messages.channel.presence, + logger = logger.withContext(tag = "Presence"), ) roomFeatures.add(presenceContributor) _presence = presenceContributor @@ -208,6 +210,7 @@ internal class DefaultRoom( roomId = roomId, clientId = clientId, realtimeChannels = realtimeClient.channels, + logger = logger.withContext(tag = "Reactions"), ) roomFeatures.add(reactionsContributor) _reactions = reactionsContributor diff --git a/chat-android/src/main/java/com/ably/chat/RoomLifecycleManager.kt b/chat-android/src/main/java/com/ably/chat/RoomLifecycleManager.kt index e8cc729a..25fe09e4 100644 --- a/chat-android/src/main/java/com/ably/chat/RoomLifecycleManager.kt +++ b/chat-android/src/main/java/com/ably/chat/RoomLifecycleManager.kt @@ -17,6 +17,7 @@ import io.ably.lib.realtime.Channel as AblyRealtimeChannel * An interface for features that contribute to the room status. */ interface ContributesToRoomLifecycle : EmitsDiscontinuities, HandlesDiscontinuity { + /** * Name of the feature */ @@ -47,9 +48,9 @@ interface ContributesToRoomLifecycle : EmitsDiscontinuities, HandlesDiscontinuit fun release() } -abstract class ContributesToRoomLifecycleImpl : ContributesToRoomLifecycle { +internal abstract class ContributesToRoomLifecycleImpl(logger: Logger) : ContributesToRoomLifecycle { - private val discontinuityEmitter = DiscontinuityEmitter() + private val discontinuityEmitter = DiscontinuityEmitter(logger) override fun onDiscontinuity(listener: EmitsDiscontinuities.Listener): Subscription { discontinuityEmitter.on(listener) diff --git a/chat-android/src/main/java/com/ably/chat/RoomReactions.kt b/chat-android/src/main/java/com/ably/chat/RoomReactions.kt index a94d4e0b..b3385224 100644 --- a/chat-android/src/main/java/com/ably/chat/RoomReactions.kt +++ b/chat-android/src/main/java/com/ably/chat/RoomReactions.kt @@ -107,7 +107,8 @@ internal class DefaultRoomReactions( roomId: String, private val clientId: String, private val realtimeChannels: AblyRealtime.Channels, -) : RoomReactions, ContributesToRoomLifecycleImpl() { + private val logger: Logger, +) : RoomReactions, ContributesToRoomLifecycleImpl(logger) { override val featureName = "reactions" diff --git a/chat-android/src/main/java/com/ably/chat/RoomStatus.kt b/chat-android/src/main/java/com/ably/chat/RoomStatus.kt index 7793641c..9d4a2a04 100644 --- a/chat-android/src/main/java/com/ably/chat/RoomStatus.kt +++ b/chat-android/src/main/java/com/ably/chat/RoomStatus.kt @@ -2,7 +2,6 @@ package com.ably.chat import io.ably.lib.types.ErrorInfo import io.ably.lib.util.EventEmitter -import io.ably.lib.util.Log /** * (CHA-RS1) @@ -156,13 +155,18 @@ interface InternalRoomLifecycle : RoomLifecycle { fun setStatus(params: NewRoomStatus) } -class RoomStatusEventEmitter : EventEmitter() { +internal class RoomStatusEventEmitter(logger: Logger) : EventEmitter() { + private val logger = logger.withContext("RoomEventEmitter") override fun apply(listener: RoomLifecycle.Listener?, event: RoomStatus?, vararg args: Any?) { try { - listener?.roomStatusChanged(args[0] as RoomStatusChange) + if (args.isNotEmpty() && args[0] is RoomStatusChange) { + listener?.roomStatusChanged(args[0] as RoomStatusChange) + } else { + logger.error("Invalid arguments received in apply method") + } } catch (t: Throwable) { - Log.e("RoomEventEmitter", "Unexpected exception calling Room Status Listener", t) + logger.error("Unexpected exception calling Room Status Listener", t) } } } @@ -177,8 +181,8 @@ internal class DefaultRoomLifecycle(logger: Logger) : InternalRoomLifecycle { override val error: ErrorInfo? get() = _error - private val externalEmitter = RoomStatusEventEmitter() - private val internalEmitter = RoomStatusEventEmitter() + private val externalEmitter = RoomStatusEventEmitter(logger) + private val internalEmitter = RoomStatusEventEmitter(logger) override fun onChange(listener: RoomLifecycle.Listener): Subscription { externalEmitter.on(listener) diff --git a/chat-android/src/main/java/com/ably/chat/Rooms.kt b/chat-android/src/main/java/com/ably/chat/Rooms.kt index 88524b12..68cd47be 100644 --- a/chat-android/src/main/java/com/ably/chat/Rooms.kt +++ b/chat-android/src/main/java/com/ably/chat/Rooms.kt @@ -167,5 +167,5 @@ internal class DefaultRooms( * Spec: CHA-RC1f3 */ private fun makeRoom(roomId: String, options: RoomOptions): DefaultRoom = - DefaultRoom(roomId, options, realtimeClient, chatApi, clientId, logger) + DefaultRoom(roomId, options.copy(), realtimeClient, chatApi, clientId, logger) } diff --git a/chat-android/src/main/java/com/ably/chat/Typing.kt b/chat-android/src/main/java/com/ably/chat/Typing.kt index ecc2ff46..9b442bd6 100644 --- a/chat-android/src/main/java/com/ably/chat/Typing.kt +++ b/chat-android/src/main/java/com/ably/chat/Typing.kt @@ -96,7 +96,7 @@ internal class DefaultTyping( private val clientId: String, private val options: TypingOptions?, private val logger: Logger, -) : Typing, ContributesToRoomLifecycleImpl() { +) : Typing, ContributesToRoomLifecycleImpl(logger) { private val typingIndicatorsChannelName = "$roomId::\$chat::\$typingIndicators" override val featureName = "typing" diff --git a/chat-android/src/main/java/com/ably/chat/Utils.kt b/chat-android/src/main/java/com/ably/chat/Utils.kt index dd89bf58..35776558 100644 --- a/chat-android/src/main/java/com/ably/chat/Utils.kt +++ b/chat-android/src/main/java/com/ably/chat/Utils.kt @@ -215,24 +215,18 @@ internal class DeferredValue { fun lifeCycleErrorInfo( errorMessage: String, errorCode: ErrorCode, - statusCode: Int = HttpStatusCode.InternalServerError, -) = ErrorInfo(errorMessage, statusCode, errorCode.code) +) = createErrorInfo(errorMessage, errorCode, HttpStatusCode.InternalServerError) fun lifeCycleException( errorMessage: String, errorCode: ErrorCode, - statusCode: Int = HttpStatusCode.InternalServerError, cause: Throwable? = null, -): AblyException = ablyException(errorMessage, errorCode, statusCode, cause) - -fun lifeCycleException(errorInfo: ErrorInfo, cause: Throwable? = null) = ablyException(errorInfo, cause) +): AblyException = createAblyException(lifeCycleErrorInfo(errorMessage, errorCode), cause) -fun ablyException(errorInfo: ErrorInfo, cause: Throwable? = null): AblyException { - cause?.let { - return AblyException.fromErrorInfo(cause, errorInfo) - } - return AblyException.fromErrorInfo(errorInfo) -} +fun lifeCycleException( + errorInfo: ErrorInfo, + cause: Throwable? = null, +): AblyException = createAblyException(errorInfo, cause) fun ablyException( errorMessage: String, @@ -240,8 +234,23 @@ fun ablyException( statusCode: Int = HttpStatusCode.BadRequest, cause: Throwable? = null, ): AblyException { - cause?.let { - return AblyException.fromErrorInfo(cause, ErrorInfo(errorMessage, statusCode, errorCode.code)) - } - return AblyException.fromErrorInfo(ErrorInfo(errorMessage, statusCode, errorCode.code)) + val errorInfo = createErrorInfo(errorMessage, errorCode, statusCode) + return createAblyException(errorInfo, cause) } + +fun ablyException( + errorInfo: ErrorInfo, + cause: Throwable? = null, +): AblyException = createAblyException(errorInfo, cause) + +private fun createErrorInfo( + errorMessage: String, + errorCode: ErrorCode, + statusCode: Int, +) = ErrorInfo(errorMessage, statusCode, errorCode.code) + +private fun createAblyException( + errorInfo: ErrorInfo, + cause: Throwable?, +) = cause?.let { AblyException.fromErrorInfo(it, errorInfo) } + ?: AblyException.fromErrorInfo(errorInfo) diff --git a/chat-android/src/test/java/com/ably/chat/MessagesTest.kt b/chat-android/src/test/java/com/ably/chat/MessagesTest.kt index af6e2631..d9dd6c57 100644 --- a/chat-android/src/test/java/com/ably/chat/MessagesTest.kt +++ b/chat-android/src/test/java/com/ably/chat/MessagesTest.kt @@ -1,5 +1,6 @@ package com.ably.chat +import com.ably.chat.room.createMockLogger import com.google.gson.JsonObject import io.ably.lib.realtime.AblyRealtime.Channels import io.ably.lib.realtime.Channel @@ -30,6 +31,7 @@ class MessagesTest { private val realtimeChannel = spyk(buildRealtimeChannel()) private val chatApi = spyk(ChatApi(realtimeClient, "clientId", EmptyLogger(LogContext(tag = "TEST")))) private lateinit var messages: DefaultMessages + private val logger = createMockLogger() private val channelStateListenerSlot = slot() @@ -45,6 +47,7 @@ class MessagesTest { roomId = "room1", realtimeChannels = realtimeChannels, chatApi = chatApi, + logger, ) } diff --git a/chat-android/src/test/java/com/ably/chat/PresenceTest.kt b/chat-android/src/test/java/com/ably/chat/PresenceTest.kt index c43f421d..3a302edf 100644 --- a/chat-android/src/test/java/com/ably/chat/PresenceTest.kt +++ b/chat-android/src/test/java/com/ably/chat/PresenceTest.kt @@ -1,5 +1,6 @@ package com.ably.chat +import com.ably.chat.room.createMockLogger import com.google.gson.JsonObject import com.google.gson.JsonPrimitive import io.ably.lib.realtime.Channel @@ -20,6 +21,7 @@ class PresenceTest { private val pubSubChannel = spyk(buildRealtimeChannel("room1::\$chat::\$messages")) private val pubSubPresence = mockk(relaxed = true) private lateinit var presence: DefaultPresence + private val logger = createMockLogger() @Before fun setUp() { @@ -27,6 +29,7 @@ class PresenceTest { clientId = "client1", channel = pubSubChannel, presence = pubSubPresence, + logger, ) } diff --git a/chat-android/src/test/java/com/ably/chat/RoomReactionsTest.kt b/chat-android/src/test/java/com/ably/chat/RoomReactionsTest.kt index 182c4e9a..2d6bf327 100644 --- a/chat-android/src/test/java/com/ably/chat/RoomReactionsTest.kt +++ b/chat-android/src/test/java/com/ably/chat/RoomReactionsTest.kt @@ -1,5 +1,6 @@ package com.ably.chat +import com.ably.chat.room.createMockLogger import com.google.gson.JsonObject import io.ably.lib.realtime.AblyRealtime.Channels import io.ably.lib.realtime.Channel @@ -19,6 +20,7 @@ class RoomReactionsTest { private val realtimeChannels = mockk(relaxed = true) private val realtimeChannel = spyk(buildRealtimeChannel("room1::\$chat::\$reactions")) private lateinit var roomReactions: DefaultRoomReactions + private val logger = createMockLogger() @Before fun setUp() { @@ -35,6 +37,7 @@ class RoomReactionsTest { roomId = "room1", clientId = "client1", realtimeChannels = realtimeChannels, + logger, ) } @@ -47,6 +50,7 @@ class RoomReactionsTest { roomId = "foo", clientId = "client1", realtimeChannels = realtimeChannels, + logger, ) assertEquals( diff --git a/chat-android/src/test/java/com/ably/chat/room/RoomTestHelpers.kt b/chat-android/src/test/java/com/ably/chat/room/RoomTestHelpers.kt index caf77a22..48035dee 100644 --- a/chat-android/src/test/java/com/ably/chat/room/RoomTestHelpers.kt +++ b/chat-android/src/test/java/com/ably/chat/room/RoomTestHelpers.kt @@ -58,9 +58,9 @@ fun createRoomFeatureMocks(roomId: String = "1234"): List(relaxed = true) val logger = createMockLogger() - val messagesContributor = spyk(DefaultMessages(roomId, realtimeClient.channels, chatApi), recordPrivateCalls = true) + val messagesContributor = spyk(DefaultMessages(roomId, realtimeClient.channels, chatApi, logger), recordPrivateCalls = true) val presenceContributor = spyk( - DefaultPresence(clientId, messagesContributor.channel, messagesContributor.channel.presence), + DefaultPresence(clientId, messagesContributor.channel, messagesContributor.channel.presence, logger), recordPrivateCalls = true, ) val occupancyContributor = spyk(DefaultOccupancy(realtimeClient.channels, chatApi, roomId, logger), recordPrivateCalls = true) @@ -68,7 +68,7 @@ fun createRoomFeatureMocks(roomId: String = "1234"): List Unit) { var members by remember { mutableStateOf(listOf()) } val coroutineScope = rememberCoroutineScope() - val presence = runBlocking { chatClient.rooms.get(Settings.ROOM_ID).presence } + val presence = runBlocking { + chatClient.rooms.get(Settings.ROOM_ID, RoomOptions.default).presence + } DisposableEffect(Unit) { var subscription: Subscription? = null