Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import org.matrix.android.sdk.api.failure.MatrixError
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError

sealed class CreateRoomFailure : Failure.FeatureFailure() {
object CreatedWithTimeout : CreateRoomFailure()
data class CreatedWithTimeout(val roomID: String) : CreateRoomFailure()
data class CreatedWithFederationFailure(val matrixError: MatrixError) : CreateRoomFailure()
data class AliasError(val aliasError: RoomAliasError) : CreateRoomFailure()
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ sealed class PeekResult {
val topic: String?,
val avatarUrl: String?,
val numJoinedMembers: Int?,
val roomType: String?,
val viaServers: List<String>
) : PeekResult()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@
package org.matrix.android.sdk.api.session.space

import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.model.RoomSummary

interface Space {

fun asRoom() : Room

/**
* A current snapshot of [RoomSummary] associated with the room
*/
fun spaceSummary(): SpaceSummary?

suspend fun addChildren(roomId: String, viaServers: List<String>, order: String?, autoJoin: Boolean = false)

suspend fun removeRoom(roomId: String)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ internal class DefaultRoomService @Inject constructor(
return createRoomTask
.configureWith(createRoomParams) {
this.callback = callback
this.retryCount = 3
}
.executeBy(taskExecutor)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.matrix.android.sdk.internal.session.room

import org.matrix.android.sdk.api.session.room.model.RoomType
import org.matrix.android.sdk.api.session.space.Space
import org.matrix.android.sdk.internal.session.space.DefaultSpace
import org.matrix.android.sdk.internal.session.space.SpaceSummaryDataSource
import javax.inject.Inject

internal interface SpaceGetter {
fun get(spaceId: String): Space?
}

internal class DefaultSpaceGetter @Inject constructor(
private val roomGetter: RoomGetter,
private val spaceSummaryDataSource: SpaceSummaryDataSource
) : SpaceGetter {

override fun get(spaceId: String): Space? {
return roomGetter.getRoom(spaceId)
?.takeIf { it.roomSummary()?.roomType == RoomType.SPACE }
?.let { DefaultSpace(it, spaceSummaryDataSource) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ internal class DefaultCreateRoomTask @Inject constructor(
.equalTo(RoomEntityFields.ROOM_ID, roomId)
}
} catch (exception: TimeoutCancellationException) {
throw CreateRoomFailure.CreatedWithTimeout
throw CreateRoomFailure.CreatedWithTimeout(roomId)
}
if (otherUserId != null) {
handleDirectChatCreation(roomId, otherUserId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
import org.matrix.android.sdk.api.session.room.model.RoomNameContent
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsFilter
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
import org.matrix.android.sdk.api.session.room.peeking.PeekResult
Expand Down Expand Up @@ -100,7 +101,8 @@ internal class DefaultPeekRoomTask @Inject constructor(
name = publicRepoResult.name,
topic = publicRepoResult.topic,
numJoinedMembers = publicRepoResult.numJoinedMembers,
viaServers = serverList
viaServers = serverList,
roomType = null // would be nice to get that from directory...
)
}

Expand Down Expand Up @@ -130,13 +132,18 @@ internal class DefaultPeekRoomTask @Inject constructor(
.distinctBy { it.stateKey }
.count()

val roomType = stateEvents
.lastOrNull { it.type == EventType.STATE_ROOM_CREATE }
?.let { it.content?.toModel<RoomCreateContent>()?.type }

return PeekResult.Success(
roomId = roomId,
alias = alias,
avatarUrl = avatarUrl,
name = name,
topic = topic,
numJoinedMembers = memberCount,
roomType = roomType,
viaServers = serverList
)
} catch (failure: Throwable) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
eventType = eventType,
body = body.toSafeJson(eventType)
)
sendStateTask.execute(params)
sendStateTask.executeRetry(params, 3)
}

private fun JsonDict.toSafeJson(eventType: String): JsonDict {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.matrix.android.sdk.internal.session.space

import io.realm.RealmConfiguration
import kotlinx.coroutines.TimeoutCancellationException
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.internal.database.awaitNotEmptyResult
import org.matrix.android.sdk.internal.database.model.SpaceSummaryEntity
import org.matrix.android.sdk.internal.database.model.SpaceSummaryEntityFields
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
import org.matrix.android.sdk.internal.task.Task
import java.util.concurrent.TimeUnit
import javax.inject.Inject

/**
* A simple wrapper of create room task that adds waiting for DB entities of spaces
*/
internal interface CreateSpaceTask : Task<CreateRoomParams, String>

internal class DefaultCreateSpaceTask @Inject constructor(
private val createRoomTask: CreateRoomTask,
@SessionDatabase private val realmConfiguration: RealmConfiguration
) : CreateSpaceTask {

override suspend fun execute(params: CreateRoomParams): String {
val spaceId = createRoomTask.execute(params)

try {
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
realm.where(SpaceSummaryEntity::class.java)
.equalTo(SpaceSummaryEntityFields.SPACE_ID, spaceId)
}
} catch (exception: TimeoutCancellationException) {
throw CreateRoomFailure.CreatedWithTimeout(spaceId)
}

return spaceId
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,19 @@ import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.space.Space
import org.matrix.android.sdk.api.session.space.SpaceSummary
import org.matrix.android.sdk.api.session.space.model.SpaceChildContent
import java.lang.IllegalArgumentException

class DefaultSpace(private val room: Room) : Space {
internal class DefaultSpace(private val room: Room, private val spaceSummaryDataSource: SpaceSummaryDataSource) : Space {

override fun asRoom(): Room {
return room
}

override fun spaceSummary(): SpaceSummary? {
return spaceSummaryDataSource.getSpaceSummary(asRoom().roomId)
}

override suspend fun addChildren(roomId: String, viaServers: List<String>, order: String?, autoJoin: Boolean) {
asRoom().sendStateEvent(
eventType = EventType.STATE_SPACE_CHILD,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import com.zhuinden.monarchy.Monarchy
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.RoomType
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
import org.matrix.android.sdk.api.session.space.CreateSpaceParams
Expand All @@ -32,40 +31,33 @@ import org.matrix.android.sdk.api.session.space.SpaceSummary
import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
import org.matrix.android.sdk.api.session.space.model.SpaceChildContent
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.session.room.RoomGetter
import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource
import org.matrix.android.sdk.internal.session.room.membership.joining.JoinRoomTask
import org.matrix.android.sdk.internal.session.room.SpaceGetter
import org.matrix.android.sdk.internal.session.room.membership.leaving.LeaveRoomTask
import org.matrix.android.sdk.internal.session.room.read.MarkAllRoomsReadTask
import org.matrix.android.sdk.internal.session.space.peeking.PeekSpaceTask
import org.matrix.android.sdk.internal.session.space.peeking.SpacePeekResult
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateBreadcrumbsTask
import org.matrix.android.sdk.internal.task.TaskExecutor
import javax.inject.Inject

internal class DefaultSpaceService @Inject constructor(
@SessionDatabase private val monarchy: Monarchy,
private val createRoomTask: CreateRoomTask,
private val joinRoomTask: JoinRoomTask,
private val createSpaceTask: CreateSpaceTask,
// private val joinRoomTask: JoinRoomTask,
private val joinSpaceTask: JoinSpaceTask,
private val markAllRoomsReadTask: MarkAllRoomsReadTask,
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
private val roomIdByAliasTask: GetRoomIdByAliasTask,
private val deleteRoomAliasTask: DeleteRoomAliasTask,
private val roomGetter: RoomGetter,
private val spaceGetter: SpaceGetter,
// private val markAllRoomsReadTask: MarkAllRoomsReadTask,
// private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
// private val roomIdByAliasTask: GetRoomIdByAliasTask,
// private val deleteRoomAliasTask: DeleteRoomAliasTask,
// private val roomGetter: RoomGetter,
private val spaceSummaryDataSource: SpaceSummaryDataSource,
private val peekSpaceTask: PeekSpaceTask,
private val resolveSpaceInfoTask: ResolveSpaceInfoTask,
private val leaveRoomTask: LeaveRoomTask,
private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
private val taskExecutor: TaskExecutor
private val leaveRoomTask: LeaveRoomTask
// private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
// private val taskExecutor: TaskExecutor
) : SpaceService {

override suspend fun createSpace(params: CreateSpaceParams): String {
return createRoomTask.execute(params)
return createSpaceTask.executeRetry(params, 3)
}

override suspend fun createSpace(name: String, topic: String?, avatarUri: Uri?, isPublic: Boolean): String {
Expand All @@ -78,9 +70,7 @@ internal class DefaultSpaceService @Inject constructor(
}

override fun getSpace(spaceId: String): Space? {
return roomGetter.getRoom(spaceId)
?.takeIf { it.roomSummary()?.roomType == RoomType.SPACE }
?.let { DefaultSpace(it) }
return spaceGetter.get(spaceId)
}

override fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<SpaceSummary>> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import dagger.Binds
import dagger.Module
import dagger.Provides
import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.android.sdk.internal.session.room.DefaultSpaceGetter
import org.matrix.android.sdk.internal.session.room.SpaceGetter
import org.matrix.android.sdk.internal.session.space.peeking.DefaultPeekSpaceTask
import org.matrix.android.sdk.internal.session.space.peeking.PeekSpaceTask
import retrofit2.Retrofit
Expand All @@ -45,4 +47,10 @@ internal abstract class SpaceModule {

@Binds
abstract fun bindJoinSpaceTask(task: DefaultJoinSpaceTask): JoinSpaceTask

@Binds
abstract fun bindSpaceGetter(getter: DefaultSpaceGetter): SpaceGetter

@Binds
abstract fun bindCreateSpaceTask(getter: DefaultCreateSpaceTask): CreateSpaceTask
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ internal data class ConfigurableTask<PARAMS, RESULT>(
val id: UUID,
val callbackThread: TaskThread,
val executionThread: TaskThread,
val callback: MatrixCallback<RESULT>
val callback: MatrixCallback<RESULT>,
val maxRetryCount: Int = 0

) : Task<PARAMS, RESULT> by task {

Expand All @@ -57,7 +58,8 @@ internal data class ConfigurableTask<PARAMS, RESULT>(
id = id,
callbackThread = callbackThread,
executionThread = executionThread,
callback = callback
callback = callback,
maxRetryCount = retryCount
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,29 @@

package org.matrix.android.sdk.internal.task

import kotlinx.coroutines.delay
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.shouldBeRetried
import timber.log.Timber

internal interface Task<PARAMS, RESULT> {

suspend fun execute(params: PARAMS): RESULT

suspend fun executeRetry(params: PARAMS, remainingRetry: Int) : RESULT {
return try {
execute(params)
} catch (failure: Throwable) {
if (failure.shouldBeRetried() && remainingRetry > 0) {
Timber.d(failure, "## TASK: Retriable error")
if (failure is Failure.ServerError) {
val waitTime = failure.error.retryAfterMillis ?: 0L
Timber.d(failure, "## TASK: Quota wait time $waitTime")
delay(waitTime + 100)
}
return executeRetry(params, remainingRetry - 1)
}
throw failure
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ internal class TaskExecutor @Inject constructor(private val coroutineDispatchers
.launch(task.callbackThread.toDispatcher()) {
val resultOrFailure = runCatching {
withContext(task.executionThread.toDispatcher()) {
Timber.v("Enqueue task $task")
Timber.v("Execute task $task on ${Thread.currentThread().name}")
task.execute(task.params)
Timber.v("## TASK: Enqueue task $task")
Timber.v("## TASK: Execute task $task on ${Thread.currentThread().name}")
task.executeRetry(task.params, task.maxRetryCount)
}
}
resultOrFailure
Expand Down
1 change: 1 addition & 0 deletions vector/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@
<activity android:name=".features.devtools.RoomDevToolActivity"/>
<activity android:name=".features.spaces.SpacePreviewActivity"/>
<activity android:name=".features.spaces.SpaceExploreActivity"/>
<activity android:name=".features.spaces.SpaceCreationActivity"/>
<!-- Services -->

<service
Expand Down
Loading