Mitigate a deadlock when loading room timelines (#6674)
This may be happening because we were not destroying focused event timelines used for the media viewer/gallery when necessary, and having several of those back paginating *may* have caused a deadlock in the event cache.
This commit is contained in:
parent
13775f4fbd
commit
30fd90abb9
9 changed files with 28 additions and 19 deletions
|
|
@ -17,6 +17,7 @@ import io.element.android.libraries.matrix.api.room.BaseRoom
|
|||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId
|
||||
import io.element.android.libraries.mediaviewer.impl.model.GroupedMediaItems
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
|
|
@ -27,10 +28,11 @@ import kotlinx.coroutines.flow.launchIn
|
|||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onCompletion
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
interface MediaGalleryDataSource {
|
||||
fun start()
|
||||
fun start(coroutineScope: CoroutineScope)
|
||||
fun groupedMediaItemsFlow(): Flow<AsyncData<GroupedMediaItems>>
|
||||
fun getLastData(): AsyncData<GroupedMediaItems>
|
||||
suspend fun loadMore(direction: Timeline.PaginationDirection)
|
||||
|
|
@ -58,7 +60,7 @@ class TimelineMediaGalleryDataSource(
|
|||
private val isStarted = AtomicBoolean(false)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun start() {
|
||||
override fun start(coroutineScope: CoroutineScope) {
|
||||
if (!isStarted.compareAndSet(false, true)) {
|
||||
return
|
||||
}
|
||||
|
|
@ -96,9 +98,12 @@ class TimelineMediaGalleryDataSource(
|
|||
groupedMediaItemsFlow.emit(AsyncData.Success(groupedMediaItems))
|
||||
}
|
||||
.onCompletion {
|
||||
timeline?.close()
|
||||
timeline?.let {
|
||||
Timber.d("Timeline media gallery data source flow completed for room ${room.roomId}, closing timeline")
|
||||
it.close()
|
||||
}
|
||||
}
|
||||
.launchIn(room.roomCoroutineScope)
|
||||
.launchIn(coroutineScope)
|
||||
}
|
||||
|
||||
override suspend fun loadMore(direction: Timeline.PaginationDirection) {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class MediaGalleryPresenter(
|
|||
.collectAsState(AsyncData.Uninitialized)
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
mediaGalleryDataSource.start()
|
||||
mediaGalleryDataSource.start(this)
|
||||
}
|
||||
|
||||
val permissions by room.permissionsAsState(MediaPermissions.DEFAULT) { perms ->
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import kotlinx.collections.immutable.ImmutableList
|
|||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
@ -62,11 +63,12 @@ class MediaViewerDataSource(
|
|||
private val localMediaStates: MutableMap<String, MutableState<AsyncData<LocalMedia>>> =
|
||||
mutableMapOf()
|
||||
|
||||
fun setup() {
|
||||
galleryDataSource.start()
|
||||
fun setup(coroutineScope: CoroutineScope) {
|
||||
galleryDataSource.start(coroutineScope)
|
||||
}
|
||||
|
||||
fun dispose() {
|
||||
Timber.d("Disposing MediaViewerDataSource, closing ${mediaFiles.size} media files")
|
||||
mediaFiles.forEach { it.close() }
|
||||
mediaFiles.clear()
|
||||
localMediaStates.clear()
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ class MediaViewerPresenter(
|
|||
var mediaBottomSheetState by remember { mutableStateOf<MediaBottomSheetState>(MediaBottomSheetState.Hidden) }
|
||||
|
||||
DisposableEffect(Unit) {
|
||||
dataSource.setup()
|
||||
dataSource.setup(coroutineScope)
|
||||
onDispose {
|
||||
dataSource.dispose()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,12 +20,13 @@ import io.element.android.libraries.mediaviewer.impl.datasource.MediaGalleryData
|
|||
import io.element.android.libraries.mediaviewer.impl.model.GroupedMediaItems
|
||||
import io.element.android.libraries.mediaviewer.impl.model.MediaItem
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
class SingleMediaGalleryDataSource(
|
||||
private val data: GroupedMediaItems,
|
||||
) : MediaGalleryDataSource {
|
||||
override fun start() = Unit
|
||||
override fun start(coroutineScope: CoroutineScope) = Unit
|
||||
override fun groupedMediaItemsFlow() = flowOf(AsyncData.Success(data))
|
||||
override fun getLastData(): AsyncData<GroupedMediaItems> = AsyncData.Success(data)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue