Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AND-172] Await Depednecy Resolve process until ChatClient is properly initialized #5514

Merged
merged 3 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### 🐞 Fixed

### ⬆️ Improved
- Internal "Resolve Dependency" process improvements. [#5514](https://github.com/GetStream/stream-chat-android/pull/5514)

### ✅ Added
- Add `Channel.membership.pinnedAt` property notifiying if/when a channel was pinned by the current user. [#5513](https://github.com/GetStream/stream-chat-android/pull/5513)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public final class io/getstream/chat/android/client/BuildConfig {
public final class io/getstream/chat/android/client/ChatClient {
public static final field Companion Lio/getstream/chat/android/client/ChatClient$Companion;
public static final field DEFAULT_SORT Lio/getstream/chat/android/models/querysort/QuerySorter;
public static final field RESOLVE_DEPENDENCY_TIMEOUT J
public final fun acceptInvite (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lio/getstream/result/call/Call;
public final fun addDevice (Lio/getstream/chat/android/models/Device;)Lio/getstream/result/call/Call;
public final fun addMembers (Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/client/query/AddMembersParams;)Lio/getstream/result/call/Call;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ import io.getstream.chat.android.client.utils.observable.Disposable
import io.getstream.chat.android.client.utils.retry.NoRetryPolicy
import io.getstream.chat.android.client.utils.stringify
import io.getstream.chat.android.core.internal.InternalStreamChatApi
import io.getstream.chat.android.core.internal.StreamHandsOff
import io.getstream.chat.android.models.AppSettings
import io.getstream.chat.android.models.Attachment
import io.getstream.chat.android.models.BannedUser
Expand Down Expand Up @@ -359,7 +360,7 @@ internal constructor(
@Suppress("ThrowsCount")
internal inline fun <reified P : DependencyResolver, reified T : Any> resolvePluginDependency(): T {
StreamLog.v(TAG) { "[resolvePluginDependency] P: ${P::class.simpleName}, T: ${T::class.simpleName}" }
val initState = clientState.initializationState.value
val initState = awaitInitializationState(RESOLVE_DEPENDENCY_TIMEOUT)
if (initState != InitializationState.COMPLETE) {
StreamLog.e(TAG) { "[resolvePluginDependency] failed (initializationState is not COMPLETE): $initState " }
throw IllegalStateException("ChatClient::connectUser() must be called before resolving any dependency")
Expand All @@ -375,6 +376,25 @@ internal constructor(
)
}

@InternalStreamChatApi
@StreamHandsOff(
"This method is used to avoid race-condition between plugin initialization and dependency resolution.",
)
public fun awaitInitializationState(timeoutMilliseconds: Long): InitializationState? {
var initState: InitializationState? = clientState.initializationState.value
var spendTime = 0L
inheritScope { Job(it) }.launch {
initState = withTimeoutOrNull(timeoutMilliseconds) {
clientState.initializationState.first { it == InitializationState.COMPLETE }
}
}
while (initState == InitializationState.INITIALIZING && spendTime < timeoutMilliseconds) {
java.lang.Thread.sleep(INITIALIZATION_DELAY)
JcMinarro marked this conversation as resolved.
Show resolved Hide resolved
spendTime += INITIALIZATION_DELAY
}
return initState
}

/**
* Error handlers for API calls.
*/
Expand Down Expand Up @@ -3947,6 +3967,7 @@ internal constructor(
private const val MESSAGE_ACTION_SHUFFLE = "shuffle"
private val THIRTY_DAYS_IN_MILLISECONDS = 30.days.inWholeMilliseconds
private const val INITIALIZATION_DELAY = 100L
public const val RESOLVE_DEPENDENCY_TIMEOUT: Long = 10_000L

private const val ARG_TYPING_PARENT_ID = "parent_id"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ internal class ChannelListViewModelTest {
fun givenCurrentUser(currentUser: User = User(id = "Jc")) = apply {
whenever(clientState.user) doReturn MutableStateFlow(currentUser)
whenever(clientState.initializationState) doReturn MutableStateFlow(InitializationState.COMPLETE)
whenever(chatClient.awaitInitializationState(any())) doReturn InitializationState.COMPLETE
}

fun givenChannelMutes(channelMutes: List<ChannelMute> = emptyList()) = apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ internal class MessageComposerViewModelTest {
whenever(clientState.user) doReturn MutableStateFlow(currentUser)
whenever(chatClient.clientState) doReturn clientState
whenever(clientState.initializationState) doReturn MutableStateFlow(InitializationState.COMPLETE)
whenever(chatClient.awaitInitializationState(any())) doReturn InitializationState.COMPLETE
}

fun givenChannelQuery(channel: Channel = Channel()) = apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import org.amshove.kluent.shouldBeEqualTo
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.RegisterExtension
import org.mockito.kotlin.any
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
Expand Down Expand Up @@ -136,6 +137,7 @@ internal class ChatClientExtensionTests {
userFlow.value = null
Unit.asCall()
}
on(it.awaitInitializationState(any())) doReturn InitializationState.COMPLETE
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ internal class ChannelListViewModelTest {
whenever(clientState.user) doReturn MutableStateFlow(currentUser)
whenever(clientState.initializationState) doReturn MutableStateFlow(InitializationState.COMPLETE)
whenever(chatClient.getCurrentUser()) doReturn currentUser
whenever(chatClient.awaitInitializationState(any())) doReturn InitializationState.COMPLETE
}

fun givenChannelMutes(channelMutes: List<ChannelMute> = emptyList()) = apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ internal class MessageComposerViewModelTest {
whenever(clientState.user) doReturn MutableStateFlow(currentUser)
whenever(chatClient.clientState) doReturn clientState
whenever(clientState.initializationState) doReturn MutableStateFlow(InitializationState.COMPLETE)
whenever(chatClient.awaitInitializationState(any())) doReturn InitializationState.COMPLETE
}

fun givenChannelQuery(channel: Channel = Channel()) = apply {
Expand Down
Loading