Merge pull request #4146 from element-hq/feature/fga/suspend_unsafe_sdk_method
fix(coroutine) : make sure to switch coroutine context
This commit is contained in:
commit
2ae511ee33
4 changed files with 118 additions and 86 deletions
|
|
@ -137,7 +137,11 @@ class RustMatrixClient(
|
||||||
|
|
||||||
private val innerRoomListService = innerSyncService.roomListService()
|
private val innerRoomListService = innerSyncService.roomListService()
|
||||||
|
|
||||||
private val rustSyncService = RustSyncService(innerSyncService, sessionCoroutineScope)
|
private val rustSyncService = RustSyncService(
|
||||||
|
inner = innerSyncService,
|
||||||
|
dispatcher = sessionDispatcher,
|
||||||
|
sessionCoroutineScope = sessionCoroutineScope
|
||||||
|
)
|
||||||
private val pushersService = RustPushersService(
|
private val pushersService = RustPushersService(
|
||||||
client = innerClient,
|
client = innerClient,
|
||||||
dispatchers = dispatchers,
|
dispatchers = dispatchers,
|
||||||
|
|
@ -283,8 +287,8 @@ class RustMatrixClient(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findDM(userId: UserId): RoomId? {
|
override suspend fun findDM(userId: UserId): RoomId? = withContext(sessionDispatcher) {
|
||||||
return innerClient.getDmRoom(userId.value)?.use { RoomId(it.id()) }
|
innerClient.getDmRoom(userId.value)?.use { RoomId(it.id()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun ignoreUser(userId: UserId): Result<Unit> = withContext(sessionDispatcher) {
|
override suspend fun ignoreUser(userId: UserId): Result<Unit> = withContext(sessionDispatcher) {
|
||||||
|
|
|
||||||
|
|
@ -329,7 +329,7 @@ class RustMatrixRoom(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun updateRoomNotificationSettings(): Result<Unit> = withContext(coroutineDispatchers.io) {
|
override suspend fun updateRoomNotificationSettings(): Result<Unit> = withContext(roomDispatcher) {
|
||||||
val currentState = _roomNotificationSettingsStateFlow.value
|
val currentState = _roomNotificationSettingsStateFlow.value
|
||||||
val currentRoomNotificationSettings = currentState.roomNotificationSettings()
|
val currentRoomNotificationSettings = currentState.roomNotificationSettings()
|
||||||
_roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Pending(prevRoomNotificationSettings = currentRoomNotificationSettings)
|
_roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Pending(prevRoomNotificationSettings = currentRoomNotificationSettings)
|
||||||
|
|
@ -345,7 +345,7 @@ class RustMatrixRoom(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun userRole(userId: UserId): Result<RoomMember.Role> = withContext(coroutineDispatchers.io) {
|
override suspend fun userRole(userId: UserId): Result<RoomMember.Role> = withContext(roomDispatcher) {
|
||||||
runCatching {
|
runCatching {
|
||||||
RoomMemberMapper.mapRole(innerRoom.suggestedRoleForUser(userId.value))
|
RoomMemberMapper.mapRole(innerRoom.suggestedRoleForUser(userId.value))
|
||||||
}
|
}
|
||||||
|
|
@ -429,56 +429,56 @@ class RustMatrixRoom(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun canUserInvite(userId: UserId): Result<Boolean> {
|
override suspend fun canUserInvite(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||||
return runCatching {
|
runCatching {
|
||||||
innerRoom.canUserInvite(userId.value)
|
innerRoom.canUserInvite(userId.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun canUserKick(userId: UserId): Result<Boolean> {
|
override suspend fun canUserKick(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||||
return runCatching {
|
runCatching {
|
||||||
innerRoom.canUserKick(userId.value)
|
innerRoom.canUserKick(userId.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun canUserBan(userId: UserId): Result<Boolean> {
|
override suspend fun canUserBan(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||||
return runCatching {
|
runCatching {
|
||||||
innerRoom.canUserBan(userId.value)
|
innerRoom.canUserBan(userId.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun canUserRedactOwn(userId: UserId): Result<Boolean> {
|
override suspend fun canUserRedactOwn(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||||
return runCatching {
|
runCatching {
|
||||||
innerRoom.canUserRedactOwn(userId.value)
|
innerRoom.canUserRedactOwn(userId.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun canUserRedactOther(userId: UserId): Result<Boolean> {
|
override suspend fun canUserRedactOther(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||||
return runCatching {
|
runCatching {
|
||||||
innerRoom.canUserRedactOther(userId.value)
|
innerRoom.canUserRedactOther(userId.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun canUserSendState(userId: UserId, type: StateEventType): Result<Boolean> {
|
override suspend fun canUserSendState(userId: UserId, type: StateEventType): Result<Boolean> = withContext(roomDispatcher) {
|
||||||
return runCatching {
|
runCatching {
|
||||||
innerRoom.canUserSendState(userId.value, type.map())
|
innerRoom.canUserSendState(userId.value, type.map())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun canUserSendMessage(userId: UserId, type: MessageEventType): Result<Boolean> {
|
override suspend fun canUserSendMessage(userId: UserId, type: MessageEventType): Result<Boolean> = withContext(roomDispatcher) {
|
||||||
return runCatching {
|
runCatching {
|
||||||
innerRoom.canUserSendMessage(userId.value, type.map())
|
innerRoom.canUserSendMessage(userId.value, type.map())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun canUserTriggerRoomNotification(userId: UserId): Result<Boolean> {
|
override suspend fun canUserTriggerRoomNotification(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||||
return runCatching {
|
runCatching {
|
||||||
innerRoom.canUserTriggerRoomNotification(userId.value)
|
innerRoom.canUserTriggerRoomNotification(userId.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun canUserPinUnpin(userId: UserId): Result<Boolean> {
|
override suspend fun canUserPinUnpin(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||||
return runCatching {
|
runCatching {
|
||||||
innerRoom.canUserPinUnpin(userId.value)
|
innerRoom.canUserPinUnpin(userId.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -676,8 +676,10 @@ class RustMatrixRoom(
|
||||||
return liveTimeline.sendVoiceMessage(file, audioInfo, waveform, progressCallback)
|
return liveTimeline.sendVoiceMessage(file, audioInfo, waveform, progressCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun typingNotice(isTyping: Boolean) = runCatching {
|
override suspend fun typingNotice(isTyping: Boolean) = withContext(roomDispatcher) {
|
||||||
innerRoom.typingNotice(isTyping)
|
runCatching {
|
||||||
|
innerRoom.typingNotice(isTyping)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun generateWidgetWebViewUrl(
|
override suspend fun generateWidgetWebViewUrl(
|
||||||
|
|
@ -685,32 +687,42 @@ class RustMatrixRoom(
|
||||||
clientId: String,
|
clientId: String,
|
||||||
languageTag: String?,
|
languageTag: String?,
|
||||||
theme: String?,
|
theme: String?,
|
||||||
) = runCatching {
|
) = withContext(roomDispatcher) {
|
||||||
widgetSettings.generateWidgetWebViewUrl(innerRoom, clientId, languageTag, theme)
|
runCatching {
|
||||||
|
widgetSettings.generateWidgetWebViewUrl(innerRoom, clientId, languageTag, theme)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result<MatrixWidgetDriver> = runCatching {
|
override fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result<MatrixWidgetDriver> {
|
||||||
RustWidgetDriver(
|
return runCatching {
|
||||||
widgetSettings = widgetSettings,
|
RustWidgetDriver(
|
||||||
room = innerRoom,
|
widgetSettings = widgetSettings,
|
||||||
widgetCapabilitiesProvider = object : WidgetCapabilitiesProvider {
|
room = innerRoom,
|
||||||
override fun acquireCapabilities(capabilities: WidgetCapabilities): WidgetCapabilities {
|
widgetCapabilitiesProvider = object : WidgetCapabilitiesProvider {
|
||||||
return getElementCallRequiredPermissions(sessionId.value, deviceId.value)
|
override fun acquireCapabilities(capabilities: WidgetCapabilities): WidgetCapabilities {
|
||||||
}
|
return getElementCallRequiredPermissions(sessionId.value, deviceId.value)
|
||||||
},
|
}
|
||||||
)
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getPermalink(): Result<String> = runCatching {
|
override suspend fun getPermalink(): Result<String> = withContext(roomDispatcher) {
|
||||||
innerRoom.matrixToPermalink()
|
runCatching {
|
||||||
|
innerRoom.matrixToPermalink()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getPermalinkFor(eventId: EventId): Result<String> = runCatching {
|
override suspend fun getPermalinkFor(eventId: EventId): Result<String> = withContext(roomDispatcher) {
|
||||||
innerRoom.matrixToEventPermalink(eventId.value)
|
runCatching {
|
||||||
|
innerRoom.matrixToEventPermalink(eventId.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun sendCallNotificationIfNeeded(): Result<Unit> = runCatching {
|
override suspend fun sendCallNotificationIfNeeded(): Result<Unit> = withContext(roomDispatcher) {
|
||||||
innerRoom.sendCallNotificationIfNeeded()
|
runCatching {
|
||||||
|
innerRoom.sendCallNotificationIfNeeded()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun setSendQueueEnabled(enabled: Boolean) {
|
override suspend fun setSendQueueEnabled(enabled: Boolean) {
|
||||||
|
|
@ -722,35 +734,45 @@ class RustMatrixRoom(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun saveComposerDraft(composerDraft: ComposerDraft): Result<Unit> = runCatching {
|
override suspend fun saveComposerDraft(composerDraft: ComposerDraft): Result<Unit> = withContext(roomDispatcher) {
|
||||||
Timber.d("saveComposerDraft: $composerDraft into $roomId")
|
runCatching {
|
||||||
innerRoom.saveComposerDraft(composerDraft.into())
|
Timber.d("saveComposerDraft: $composerDraft into $roomId")
|
||||||
|
innerRoom.saveComposerDraft(composerDraft.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun loadComposerDraft(): Result<ComposerDraft?> = runCatching {
|
override suspend fun loadComposerDraft(): Result<ComposerDraft?> = withContext(roomDispatcher) {
|
||||||
Timber.d("loadComposerDraft for $roomId")
|
runCatching {
|
||||||
innerRoom.loadComposerDraft()?.into()
|
Timber.d("loadComposerDraft for $roomId")
|
||||||
|
innerRoom.loadComposerDraft()?.into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun clearComposerDraft(): Result<Unit> = runCatching {
|
override suspend fun clearComposerDraft(): Result<Unit> = withContext(roomDispatcher) {
|
||||||
Timber.d("clearComposerDraft for $roomId")
|
runCatching {
|
||||||
innerRoom.clearComposerDraft()
|
Timber.d("clearComposerDraft for $roomId")
|
||||||
|
innerRoom.clearComposerDraft()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun ignoreDeviceTrustAndResend(devices: Map<UserId, List<DeviceId>>, sendHandle: SendHandle) = runCatching {
|
override suspend fun ignoreDeviceTrustAndResend(devices: Map<UserId, List<DeviceId>>, sendHandle: SendHandle) = withContext(roomDispatcher) {
|
||||||
innerRoom.ignoreDeviceTrustAndResend(
|
runCatching {
|
||||||
devices = devices.entries.associate { entry ->
|
innerRoom.ignoreDeviceTrustAndResend(
|
||||||
entry.key.value to entry.value.map { it.value }
|
devices = devices.entries.associate { entry ->
|
||||||
},
|
entry.key.value to entry.value.map { it.value }
|
||||||
sendHandle = (sendHandle as RustSendHandle).inner,
|
},
|
||||||
)
|
sendHandle = (sendHandle as RustSendHandle).inner,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun withdrawVerificationAndResend(userIds: List<UserId>, sendHandle: SendHandle) = runCatching {
|
override suspend fun withdrawVerificationAndResend(userIds: List<UserId>, sendHandle: SendHandle) = withContext(roomDispatcher) {
|
||||||
innerRoom.withdrawVerificationAndResend(
|
runCatching {
|
||||||
userIds = userIds.map { it.value },
|
innerRoom.withdrawVerificationAndResend(
|
||||||
sendHandle = (sendHandle as RustSendHandle).inner,
|
userIds = userIds.map { it.value },
|
||||||
)
|
sendHandle = (sendHandle as RustSendHandle).inner,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTimeline(
|
private fun createTimeline(
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.sync
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.sync.SyncService
|
import io.element.android.libraries.matrix.api.sync.SyncService
|
||||||
import io.element.android.libraries.matrix.api.sync.SyncState
|
import io.element.android.libraries.matrix.api.sync.SyncState
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.NonCancellable
|
import kotlinx.coroutines.NonCancellable
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
|
@ -24,31 +25,36 @@ import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import org.matrix.rustcomponents.sdk.SyncService as InnerSyncService
|
import org.matrix.rustcomponents.sdk.SyncService as InnerSyncService
|
||||||
|
|
||||||
class RustSyncService(
|
class RustSyncService(
|
||||||
private val innerSyncService: InnerSyncService,
|
private val inner: InnerSyncService,
|
||||||
|
private val dispatcher: CoroutineDispatcher,
|
||||||
sessionCoroutineScope: CoroutineScope
|
sessionCoroutineScope: CoroutineScope
|
||||||
) : SyncService {
|
) : SyncService {
|
||||||
private val isServiceReady = AtomicBoolean(true)
|
private val isServiceReady = AtomicBoolean(true)
|
||||||
|
|
||||||
override suspend fun startSync() = runCatching {
|
override suspend fun startSync() = withContext(dispatcher) {
|
||||||
if (!isServiceReady.get()) {
|
runCatching {
|
||||||
Timber.d("Can't start sync: service is not ready")
|
if (!isServiceReady.get()) {
|
||||||
return@runCatching
|
Timber.d("Can't start sync: service is not ready")
|
||||||
|
return@runCatching
|
||||||
|
}
|
||||||
|
Timber.i("Start sync")
|
||||||
|
inner.start()
|
||||||
|
}.onFailure {
|
||||||
|
Timber.d("Start sync failed: $it")
|
||||||
}
|
}
|
||||||
Timber.i("Start sync")
|
|
||||||
innerSyncService.start()
|
|
||||||
}.onFailure {
|
|
||||||
Timber.d("Start sync failed: $it")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun stopSync() = runCatching {
|
override suspend fun stopSync() = withContext(dispatcher) {
|
||||||
if (!isServiceReady.get()) {
|
runCatching {
|
||||||
Timber.d("Can't stop sync: service is not ready")
|
if (!isServiceReady.get()) {
|
||||||
return@runCatching
|
Timber.d("Can't stop sync: service is not ready")
|
||||||
|
return@runCatching
|
||||||
|
}
|
||||||
|
Timber.i("Stop sync")
|
||||||
|
inner.stop()
|
||||||
|
}.onFailure {
|
||||||
|
Timber.d("Stop sync failed: $it")
|
||||||
}
|
}
|
||||||
Timber.i("Stop sync")
|
|
||||||
innerSyncService.stop()
|
|
||||||
}.onFailure {
|
|
||||||
Timber.d("Stop sync failed: $it")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun destroy() = withContext(NonCancellable) {
|
suspend fun destroy() = withContext(NonCancellable) {
|
||||||
|
|
@ -59,7 +65,7 @@ class RustSyncService(
|
||||||
}
|
}
|
||||||
|
|
||||||
override val syncState: StateFlow<SyncState> =
|
override val syncState: StateFlow<SyncState> =
|
||||||
innerSyncService.stateFlow()
|
inner.stateFlow()
|
||||||
.map(SyncServiceState::toSyncState)
|
.map(SyncServiceState::toSyncState)
|
||||||
.onEach { state ->
|
.onEach { state ->
|
||||||
Timber.i("Sync state=$state")
|
Timber.i("Sync state=$state")
|
||||||
|
|
|
||||||
|
|
@ -158,8 +158,8 @@ class RustTimeline(
|
||||||
|
|
||||||
override val membershipChangeEventReceived: Flow<Unit> = timelineDiffProcessor.membershipChangeEventReceived
|
override val membershipChangeEventReceived: Flow<Unit> = timelineDiffProcessor.membershipChangeEventReceived
|
||||||
|
|
||||||
override suspend fun sendReadReceipt(eventId: EventId, receiptType: ReceiptType): Result<Unit> {
|
override suspend fun sendReadReceipt(eventId: EventId, receiptType: ReceiptType): Result<Unit> = withContext(dispatcher) {
|
||||||
return runCatching {
|
runCatching {
|
||||||
inner.sendReadReceipt(receiptType.toRustReceiptType(), eventId.value)
|
inner.sendReadReceipt(receiptType.toRustReceiptType(), eventId.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -590,8 +590,8 @@ class RustTimeline(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun fetchDetailsForEvent(eventId: EventId): Result<Unit> {
|
private suspend fun fetchDetailsForEvent(eventId: EventId): Result<Unit> = withContext(dispatcher) {
|
||||||
return runCatching {
|
runCatching {
|
||||||
inner.fetchDetailsForEvent(eventId.value)
|
inner.fetchDetailsForEvent(eventId.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue