Skip to content

Commit 0d63610

Browse files
authored
Merge pull request #4146 from element-hq/feature/fga/suspend_unsafe_sdk_method
fix(coroutine) : make sure to switch coroutine context
2 parents 46119ae + 331f692 commit 0d63610

File tree

4 files changed

+118
-86
lines changed

4 files changed

+118
-86
lines changed

libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt

+7-3
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,11 @@ class RustMatrixClient(
137137

138138
private val innerRoomListService = innerSyncService.roomListService()
139139

140-
private val rustSyncService = RustSyncService(innerSyncService, sessionCoroutineScope)
140+
private val rustSyncService = RustSyncService(
141+
inner = innerSyncService,
142+
dispatcher = sessionDispatcher,
143+
sessionCoroutineScope = sessionCoroutineScope
144+
)
141145
private val pushersService = RustPushersService(
142146
client = innerClient,
143147
dispatchers = dispatchers,
@@ -283,8 +287,8 @@ class RustMatrixClient(
283287
}
284288
}
285289

286-
override suspend fun findDM(userId: UserId): RoomId? {
287-
return innerClient.getDmRoom(userId.value)?.use { RoomId(it.id()) }
290+
override suspend fun findDM(userId: UserId): RoomId? = withContext(sessionDispatcher) {
291+
innerClient.getDmRoom(userId.value)?.use { RoomId(it.id()) }
288292
}
289293

290294
override suspend fun ignoreUser(userId: UserId): Result<Unit> = withContext(sessionDispatcher) {

libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt

+83-61
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ class RustMatrixRoom(
329329
}
330330
}
331331

332-
override suspend fun updateRoomNotificationSettings(): Result<Unit> = withContext(coroutineDispatchers.io) {
332+
override suspend fun updateRoomNotificationSettings(): Result<Unit> = withContext(roomDispatcher) {
333333
val currentState = _roomNotificationSettingsStateFlow.value
334334
val currentRoomNotificationSettings = currentState.roomNotificationSettings()
335335
_roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Pending(prevRoomNotificationSettings = currentRoomNotificationSettings)
@@ -345,7 +345,7 @@ class RustMatrixRoom(
345345
}
346346
}
347347

348-
override suspend fun userRole(userId: UserId): Result<RoomMember.Role> = withContext(coroutineDispatchers.io) {
348+
override suspend fun userRole(userId: UserId): Result<RoomMember.Role> = withContext(roomDispatcher) {
349349
runCatching {
350350
RoomMemberMapper.mapRole(innerRoom.suggestedRoleForUser(userId.value))
351351
}
@@ -429,56 +429,56 @@ class RustMatrixRoom(
429429
}
430430
}
431431

432-
override suspend fun canUserInvite(userId: UserId): Result<Boolean> {
433-
return runCatching {
432+
override suspend fun canUserInvite(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
433+
runCatching {
434434
innerRoom.canUserInvite(userId.value)
435435
}
436436
}
437437

438-
override suspend fun canUserKick(userId: UserId): Result<Boolean> {
439-
return runCatching {
438+
override suspend fun canUserKick(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
439+
runCatching {
440440
innerRoom.canUserKick(userId.value)
441441
}
442442
}
443443

444-
override suspend fun canUserBan(userId: UserId): Result<Boolean> {
445-
return runCatching {
444+
override suspend fun canUserBan(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
445+
runCatching {
446446
innerRoom.canUserBan(userId.value)
447447
}
448448
}
449449

450-
override suspend fun canUserRedactOwn(userId: UserId): Result<Boolean> {
451-
return runCatching {
450+
override suspend fun canUserRedactOwn(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
451+
runCatching {
452452
innerRoom.canUserRedactOwn(userId.value)
453453
}
454454
}
455455

456-
override suspend fun canUserRedactOther(userId: UserId): Result<Boolean> {
457-
return runCatching {
456+
override suspend fun canUserRedactOther(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
457+
runCatching {
458458
innerRoom.canUserRedactOther(userId.value)
459459
}
460460
}
461461

462-
override suspend fun canUserSendState(userId: UserId, type: StateEventType): Result<Boolean> {
463-
return runCatching {
462+
override suspend fun canUserSendState(userId: UserId, type: StateEventType): Result<Boolean> = withContext(roomDispatcher) {
463+
runCatching {
464464
innerRoom.canUserSendState(userId.value, type.map())
465465
}
466466
}
467467

468-
override suspend fun canUserSendMessage(userId: UserId, type: MessageEventType): Result<Boolean> {
469-
return runCatching {
468+
override suspend fun canUserSendMessage(userId: UserId, type: MessageEventType): Result<Boolean> = withContext(roomDispatcher) {
469+
runCatching {
470470
innerRoom.canUserSendMessage(userId.value, type.map())
471471
}
472472
}
473473

474-
override suspend fun canUserTriggerRoomNotification(userId: UserId): Result<Boolean> {
475-
return runCatching {
474+
override suspend fun canUserTriggerRoomNotification(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
475+
runCatching {
476476
innerRoom.canUserTriggerRoomNotification(userId.value)
477477
}
478478
}
479479

480-
override suspend fun canUserPinUnpin(userId: UserId): Result<Boolean> {
481-
return runCatching {
480+
override suspend fun canUserPinUnpin(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
481+
runCatching {
482482
innerRoom.canUserPinUnpin(userId.value)
483483
}
484484
}
@@ -676,41 +676,53 @@ class RustMatrixRoom(
676676
return liveTimeline.sendVoiceMessage(file, audioInfo, waveform, progressCallback)
677677
}
678678

679-
override suspend fun typingNotice(isTyping: Boolean) = runCatching {
680-
innerRoom.typingNotice(isTyping)
679+
override suspend fun typingNotice(isTyping: Boolean) = withContext(roomDispatcher) {
680+
runCatching {
681+
innerRoom.typingNotice(isTyping)
682+
}
681683
}
682684

683685
override suspend fun generateWidgetWebViewUrl(
684686
widgetSettings: MatrixWidgetSettings,
685687
clientId: String,
686688
languageTag: String?,
687689
theme: String?,
688-
) = runCatching {
689-
widgetSettings.generateWidgetWebViewUrl(innerRoom, clientId, languageTag, theme)
690+
) = withContext(roomDispatcher) {
691+
runCatching {
692+
widgetSettings.generateWidgetWebViewUrl(innerRoom, clientId, languageTag, theme)
693+
}
690694
}
691695

692-
override fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result<MatrixWidgetDriver> = runCatching {
693-
RustWidgetDriver(
694-
widgetSettings = widgetSettings,
695-
room = innerRoom,
696-
widgetCapabilitiesProvider = object : WidgetCapabilitiesProvider {
697-
override fun acquireCapabilities(capabilities: WidgetCapabilities): WidgetCapabilities {
698-
return getElementCallRequiredPermissions(sessionId.value, deviceId.value)
699-
}
700-
},
701-
)
696+
override fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result<MatrixWidgetDriver> {
697+
return runCatching {
698+
RustWidgetDriver(
699+
widgetSettings = widgetSettings,
700+
room = innerRoom,
701+
widgetCapabilitiesProvider = object : WidgetCapabilitiesProvider {
702+
override fun acquireCapabilities(capabilities: WidgetCapabilities): WidgetCapabilities {
703+
return getElementCallRequiredPermissions(sessionId.value, deviceId.value)
704+
}
705+
},
706+
)
707+
}
702708
}
703709

704-
override suspend fun getPermalink(): Result<String> = runCatching {
705-
innerRoom.matrixToPermalink()
710+
override suspend fun getPermalink(): Result<String> = withContext(roomDispatcher) {
711+
runCatching {
712+
innerRoom.matrixToPermalink()
713+
}
706714
}
707715

708-
override suspend fun getPermalinkFor(eventId: EventId): Result<String> = runCatching {
709-
innerRoom.matrixToEventPermalink(eventId.value)
716+
override suspend fun getPermalinkFor(eventId: EventId): Result<String> = withContext(roomDispatcher) {
717+
runCatching {
718+
innerRoom.matrixToEventPermalink(eventId.value)
719+
}
710720
}
711721

712-
override suspend fun sendCallNotificationIfNeeded(): Result<Unit> = runCatching {
713-
innerRoom.sendCallNotificationIfNeeded()
722+
override suspend fun sendCallNotificationIfNeeded(): Result<Unit> = withContext(roomDispatcher) {
723+
runCatching {
724+
innerRoom.sendCallNotificationIfNeeded()
725+
}
714726
}
715727

716728
override suspend fun setSendQueueEnabled(enabled: Boolean) {
@@ -722,35 +734,45 @@ class RustMatrixRoom(
722734
}
723735
}
724736

725-
override suspend fun saveComposerDraft(composerDraft: ComposerDraft): Result<Unit> = runCatching {
726-
Timber.d("saveComposerDraft: $composerDraft into $roomId")
727-
innerRoom.saveComposerDraft(composerDraft.into())
737+
override suspend fun saveComposerDraft(composerDraft: ComposerDraft): Result<Unit> = withContext(roomDispatcher) {
738+
runCatching {
739+
Timber.d("saveComposerDraft: $composerDraft into $roomId")
740+
innerRoom.saveComposerDraft(composerDraft.into())
741+
}
728742
}
729743

730-
override suspend fun loadComposerDraft(): Result<ComposerDraft?> = runCatching {
731-
Timber.d("loadComposerDraft for $roomId")
732-
innerRoom.loadComposerDraft()?.into()
744+
override suspend fun loadComposerDraft(): Result<ComposerDraft?> = withContext(roomDispatcher) {
745+
runCatching {
746+
Timber.d("loadComposerDraft for $roomId")
747+
innerRoom.loadComposerDraft()?.into()
748+
}
733749
}
734750

735-
override suspend fun clearComposerDraft(): Result<Unit> = runCatching {
736-
Timber.d("clearComposerDraft for $roomId")
737-
innerRoom.clearComposerDraft()
751+
override suspend fun clearComposerDraft(): Result<Unit> = withContext(roomDispatcher) {
752+
runCatching {
753+
Timber.d("clearComposerDraft for $roomId")
754+
innerRoom.clearComposerDraft()
755+
}
738756
}
739757

740-
override suspend fun ignoreDeviceTrustAndResend(devices: Map<UserId, List<DeviceId>>, sendHandle: SendHandle) = runCatching {
741-
innerRoom.ignoreDeviceTrustAndResend(
742-
devices = devices.entries.associate { entry ->
743-
entry.key.value to entry.value.map { it.value }
744-
},
745-
sendHandle = (sendHandle as RustSendHandle).inner,
746-
)
758+
override suspend fun ignoreDeviceTrustAndResend(devices: Map<UserId, List<DeviceId>>, sendHandle: SendHandle) = withContext(roomDispatcher) {
759+
runCatching {
760+
innerRoom.ignoreDeviceTrustAndResend(
761+
devices = devices.entries.associate { entry ->
762+
entry.key.value to entry.value.map { it.value }
763+
},
764+
sendHandle = (sendHandle as RustSendHandle).inner,
765+
)
766+
}
747767
}
748768

749-
override suspend fun withdrawVerificationAndResend(userIds: List<UserId>, sendHandle: SendHandle) = runCatching {
750-
innerRoom.withdrawVerificationAndResend(
751-
userIds = userIds.map { it.value },
752-
sendHandle = (sendHandle as RustSendHandle).inner,
753-
)
769+
override suspend fun withdrawVerificationAndResend(userIds: List<UserId>, sendHandle: SendHandle) = withContext(roomDispatcher) {
770+
runCatching {
771+
innerRoom.withdrawVerificationAndResend(
772+
userIds = userIds.map { it.value },
773+
sendHandle = (sendHandle as RustSendHandle).inner,
774+
)
775+
}
754776
}
755777

756778
private fun createTimeline(

libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt

+24-18
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.sync
99

1010
import io.element.android.libraries.matrix.api.sync.SyncService
1111
import io.element.android.libraries.matrix.api.sync.SyncState
12+
import kotlinx.coroutines.CoroutineDispatcher
1213
import kotlinx.coroutines.CoroutineScope
1314
import kotlinx.coroutines.NonCancellable
1415
import kotlinx.coroutines.flow.SharingStarted
@@ -24,31 +25,36 @@ import java.util.concurrent.atomic.AtomicBoolean
2425
import org.matrix.rustcomponents.sdk.SyncService as InnerSyncService
2526

2627
class RustSyncService(
27-
private val innerSyncService: InnerSyncService,
28+
private val inner: InnerSyncService,
29+
private val dispatcher: CoroutineDispatcher,
2830
sessionCoroutineScope: CoroutineScope
2931
) : SyncService {
3032
private val isServiceReady = AtomicBoolean(true)
3133

32-
override suspend fun startSync() = runCatching {
33-
if (!isServiceReady.get()) {
34-
Timber.d("Can't start sync: service is not ready")
35-
return@runCatching
34+
override suspend fun startSync() = withContext(dispatcher) {
35+
runCatching {
36+
if (!isServiceReady.get()) {
37+
Timber.d("Can't start sync: service is not ready")
38+
return@runCatching
39+
}
40+
Timber.i("Start sync")
41+
inner.start()
42+
}.onFailure {
43+
Timber.d("Start sync failed: $it")
3644
}
37-
Timber.i("Start sync")
38-
innerSyncService.start()
39-
}.onFailure {
40-
Timber.d("Start sync failed: $it")
4145
}
4246

43-
override suspend fun stopSync() = runCatching {
44-
if (!isServiceReady.get()) {
45-
Timber.d("Can't stop sync: service is not ready")
46-
return@runCatching
47+
override suspend fun stopSync() = withContext(dispatcher) {
48+
runCatching {
49+
if (!isServiceReady.get()) {
50+
Timber.d("Can't stop sync: service is not ready")
51+
return@runCatching
52+
}
53+
Timber.i("Stop sync")
54+
inner.stop()
55+
}.onFailure {
56+
Timber.d("Stop sync failed: $it")
4757
}
48-
Timber.i("Stop sync")
49-
innerSyncService.stop()
50-
}.onFailure {
51-
Timber.d("Stop sync failed: $it")
5258
}
5359

5460
suspend fun destroy() = withContext(NonCancellable) {
@@ -59,7 +65,7 @@ class RustSyncService(
5965
}
6066

6167
override val syncState: StateFlow<SyncState> =
62-
innerSyncService.stateFlow()
68+
inner.stateFlow()
6369
.map(SyncServiceState::toSyncState)
6470
.onEach { state ->
6571
Timber.i("Sync state=$state")

libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ class RustTimeline(
158158

159159
override val membershipChangeEventReceived: Flow<Unit> = timelineDiffProcessor.membershipChangeEventReceived
160160

161-
override suspend fun sendReadReceipt(eventId: EventId, receiptType: ReceiptType): Result<Unit> {
162-
return runCatching {
161+
override suspend fun sendReadReceipt(eventId: EventId, receiptType: ReceiptType): Result<Unit> = withContext(dispatcher) {
162+
runCatching {
163163
inner.sendReadReceipt(receiptType.toRustReceiptType(), eventId.value)
164164
}
165165
}
@@ -590,8 +590,8 @@ class RustTimeline(
590590
}
591591
}
592592

593-
private suspend fun fetchDetailsForEvent(eventId: EventId): Result<Unit> {
594-
return runCatching {
593+
private suspend fun fetchDetailsForEvent(eventId: EventId): Result<Unit> = withContext(dispatcher) {
594+
runCatching {
595595
inner.fetchDetailsForEvent(eventId.value)
596596
}
597597
}

0 commit comments

Comments
 (0)