Skip to content

Commit

Permalink
refactor: only have one main query for inserting/updating users
Browse files Browse the repository at this point in the history
  • Loading branch information
typfel committed Oct 9, 2023
1 parent fc867fa commit 723dd25
Show file tree
Hide file tree
Showing 40 changed files with 307 additions and 526 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ internal class ConnectionDataSource(
)
insertConversationFromConnection(connection)
// should we insert first user before creating conversation ?
userDAO.insertUser(userEntity)
userDAO.upsertUser(userEntity)
connectionDAO.insertConnection(connectionMapper.modelToDao(connection))
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ internal class ConversationGroupRepositoryImpl(
private val selfUserId: UserId,
private val teamIdProvider: SelfTeamIdProvider,
private val conversationMapper: ConversationMapper = MapperProvider.conversationMapper(selfUserId),
private val eventMapper: EventMapper = MapperProvider.eventMapper(),
private val eventMapper: EventMapper = MapperProvider.eventMapper(selfUserId),
private val protocolInfoMapper: ProtocolInfoMapper = MapperProvider.protocolInfoMapper(),
) : ConversationGroupRepository {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ internal class MLSConversationDataSource(

private suspend fun processCommitBundleEvents(events: List<EventContentDTO>) {
events.forEach { eventContentDTO ->
val event = MapperProvider.eventMapper().fromEventContentDTO("", eventContentDTO, true, false)
val event = MapperProvider.eventMapper(selfUserId).fromEventContentDTO("", eventContentDTO, true, false)
if (event is Event.Conversation) {
commitBundleEventReceiver.onEvent(event)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ sealed class Event(open val id: String, open val transient: Boolean, open val li
override val id: String,
override val transient: Boolean,
override val live: Boolean,
val userId: String,
val userId: UserId,
val accentId: Int?,
val ssoIdDeleted: Boolean?,
val name: String?,
Expand All @@ -645,7 +645,7 @@ sealed class Event(open val id: String, open val transient: Boolean, open val li
override fun toLogMap(): Map<String, Any?> = mapOf(
typeKey to "User.Update",
idKey to id.obfuscateId(),
userIdKey to userId.obfuscateId()
userIdKey to userId.toLogString()
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import com.wire.kalium.logic.data.event.Event.UserProperty.TypingIndicatorModeSe
import com.wire.kalium.logic.data.featureConfig.FeatureConfigMapper
import com.wire.kalium.logic.data.id.SubconversationId
import com.wire.kalium.logic.data.id.toModel
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.data.user.toModel
import com.wire.kalium.logic.di.MapperProvider
import com.wire.kalium.logic.util.Base64
Expand All @@ -51,12 +52,13 @@ import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.SerializationException
import kotlinx.serialization.serializer

@Suppress("TooManyFunctions")
@Suppress("TooManyFunctions", "LongParameterList")
class EventMapper(
private val memberMapper: MemberMapper,
private val connectionMapper: ConnectionMapper,
private val featureConfigMapper: FeatureConfigMapper,
private val roleMapper: ConversationRoleMapper,
private val selfUserId: UserId,
private val receiptModeMapper: ReceiptModeMapper = MapperProvider.receiptModeMapper(),
private val clientMapper: ClientMapper = MapperProvider.clientMapper()
) {
Expand Down Expand Up @@ -653,7 +655,7 @@ class EventMapper(
live: Boolean
) = Event.User.Update(
id = id,
userId = event.userData.nonQualifiedUserId,
userId = UserId(event.userData.nonQualifiedUserId, selfUserId.domain),
accentId = event.userData.accentId,
ssoIdDeleted = event.userData.ssoIdDeleted,
name = event.userData.name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.wire.kalium.logic.CoreFailure
import com.wire.kalium.logic.NetworkFailure
import com.wire.kalium.logic.StorageFailure
import com.wire.kalium.logic.data.conversation.ClientId
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.di.MapperProvider
import com.wire.kalium.logic.feature.CurrentClientIdProvider
import com.wire.kalium.logic.functional.Either
Expand Down Expand Up @@ -81,7 +82,8 @@ class EventDataSource(
private val notificationApi: NotificationApi,
private val metadataDAO: MetadataDAO,
private val currentClientId: CurrentClientIdProvider,
private val eventMapper: EventMapper = MapperProvider.eventMapper()
private val selfUserId: UserId,
private val eventMapper: EventMapper = MapperProvider.eventMapper(selfUserId)
) : EventRepository {

// TODO(edge-case): handle Missing notification response (notify user that some messages are missing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,16 @@ internal class TeamDataSource(
*/
if (teamMemberList.hasMore.not()) {
teamMemberList.members.map { teamMember ->
userMapper.fromTeamMemberToDaoModel(
teamId = teamId,
nonQualifiedUserId = teamMember.nonQualifiedUserId,
permissionCode = teamMember.permissions?.own,
userDomain = userDomain,
)
val userId = QualifiedIDEntity(teamMember.nonQualifiedUserId, userDomain)
val userType = userTypeEntityTypeMapper.teamRoleCodeToUserType(teamMember.permissions?.own)
userId to userType
}
} else {
listOf()
}
}.flatMap { teamMembers ->
wrapStorageRequest {
userDAO.upsertTeamMembersTypes(teamMembers)
userDAO.upsertTeamMemberUserTypes(teamMembers.toMap())
}
}

Expand All @@ -123,13 +120,9 @@ internal class TeamDataSource(

override suspend fun updateMemberRole(teamId: String, userId: String, permissionCode: Int?): Either<CoreFailure, Unit> {
return wrapStorageRequest {
val user = userMapper.fromTeamMemberToDaoModel(
teamId = TeamId(teamId),
nonQualifiedUserId = userId,
userDomain = selfUserId.domain,
permissionCode = permissionCode
)
userDAO.upsertTeamMembersTypes(listOf(user))
userDAO.upsertTeamMemberUserTypes(mapOf(
QualifiedIDEntity(userId, selfUserId.domain) to userTypeEntityTypeMapper.teamRoleCodeToUserType(permissionCode)
))
}
}

Expand All @@ -139,7 +132,7 @@ internal class TeamDataSource(
teamId = teamId,
userId = userId,
)
}.flatMap { _ ->
}.flatMap { _ -> // TODO jacob why dow we fetch team member info if we don't use the response?
wrapApiRequest { userDetailsApi.getUserInfo(userId = QualifiedID(userId, selfUserId.domain)) }
.flatMap { userProfileDTO ->
wrapStorageRequest {
Expand All @@ -154,7 +147,7 @@ internal class TeamDataSource(
isService = userProfileDTO.service != null
)
)
userDAO.insertUser(userEntity)
userDAO.upsertUser(userEntity)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@ import com.wire.kalium.logic.data.id.NetworkQualifiedId
import com.wire.kalium.logic.data.id.TeamId
import com.wire.kalium.logic.data.id.toDao
import com.wire.kalium.logic.data.id.toModel
import com.wire.kalium.logic.data.user.type.UserEntityTypeMapper
import com.wire.kalium.logic.di.MapperProvider
import com.wire.kalium.network.api.base.authenticated.self.UserUpdateRequest
import com.wire.kalium.network.api.base.model.AssetSizeDTO
import com.wire.kalium.network.api.base.model.NonQualifiedUserId
import com.wire.kalium.network.api.base.model.SelfUserDTO
import com.wire.kalium.network.api.base.model.SupportedProtocolDTO
import com.wire.kalium.network.api.base.model.UserAssetDTO
Expand All @@ -38,6 +36,7 @@ import com.wire.kalium.network.api.base.model.getCompleteAssetOrNull
import com.wire.kalium.network.api.base.model.getPreviewAssetOrNull
import com.wire.kalium.persistence.dao.BotIdEntity
import com.wire.kalium.persistence.dao.ConnectionEntity
import com.wire.kalium.persistence.dao.PartialUserEntity
import com.wire.kalium.persistence.dao.QualifiedIDEntity
import com.wire.kalium.persistence.dao.SupportedProtocolEntity
import com.wire.kalium.persistence.dao.UserAvailabilityStatusEntity
Expand Down Expand Up @@ -68,14 +67,7 @@ interface UserMapper {
updateRequest: UserUpdateRequest
): UserEntity

fun fromTeamMemberToDaoModel(
teamId: TeamId,
nonQualifiedUserId: NonQualifiedUserId,
permissionCode: Int?,
userDomain: String,
): UserEntity

fun fromUserUpdateEventToUserEntity(event: Event.User.Update, userEntity: UserEntity): UserEntity
fun fromUserUpdateEventToPartialUserEntity(event: Event.User.Update): PartialUserEntity

fun fromUserProfileDtoToUserEntity(
userProfile: UserProfileDTO,
Expand All @@ -88,8 +80,7 @@ interface UserMapper {
internal class UserMapperImpl(
private val idMapper: IdMapper = MapperProvider.idMapper(),
private val availabilityStatusMapper: AvailabilityStatusMapper = MapperProvider.availabilityStatusMapper(),
private val connectionStateMapper: ConnectionStateMapper = MapperProvider.connectionStateMapper(),
private val userEntityTypeMapper: UserEntityTypeMapper = MapperProvider.userTypeEntityMapper()
private val connectionStateMapper: ConnectionStateMapper = MapperProvider.connectionStateMapper()
) : UserMapper {

override fun fromUserEntityToSelfUser(userEntity: UserEntity) = with(userEntity) {
Expand Down Expand Up @@ -128,7 +119,7 @@ internal class UserMapperImpl(
deleted = false,
expiresAt = expiresAt,
defederated = false,
supportedProtocols = supportedProtocols?.toDao(),
supportedProtocols = supportedProtocols?.toDao() ?: setOf(SupportedProtocolEntity.PROTEUS),
activeOneOnOneConversationId = null
)
}
Expand Down Expand Up @@ -184,39 +175,6 @@ internal class UserMapperImpl(
)
)

/**
* Null and default/hardcoded values will be replaced later when fetching known users.
*/
override fun fromTeamMemberToDaoModel(
teamId: TeamId,
nonQualifiedUserId: NonQualifiedUserId,
permissionCode: Int?,
userDomain: String,
): UserEntity =
UserEntity(
id = QualifiedIDEntity(
value = nonQualifiedUserId,
domain = userDomain
),
name = null,
handle = null,
email = null,
phone = null,
accentId = 1,
team = teamId.value,
connectionStatus = ConnectionEntity.State.ACCEPTED,
previewAssetId = null,
completeAssetId = null,
availabilityStatus = UserAvailabilityStatusEntity.NONE,
userType = userEntityTypeMapper.teamRoleCodeToUserType(permissionCode),
botService = null,
deleted = false,
expiresAt = null,
defederated = false,
supportedProtocols = null,
activeOneOnOneConversationId = null
)

override fun fromUserProfileDtoToUserEntity(
userProfile: UserProfileDTO,
connectionState: ConnectionEntity.State,
Expand Down Expand Up @@ -244,21 +202,16 @@ internal class UserMapperImpl(
activeOneOnOneConversationId = null
)

override fun fromUserUpdateEventToUserEntity(event: Event.User.Update, userEntity: UserEntity): UserEntity {
return userEntity.let { persistedEntity ->
persistedEntity.copy(
email = event.email ?: persistedEntity.email,
name = event.name ?: persistedEntity.name,
handle = event.handle ?: persistedEntity.handle,
accentId = event.accentId ?: persistedEntity.accentId,
previewAssetId = event.previewAssetId?.let { QualifiedIDEntity(it, persistedEntity.id.domain) }
?: persistedEntity.previewAssetId,
completeAssetId = event.completeAssetId?.let { QualifiedIDEntity(it, persistedEntity.id.domain) }
?: persistedEntity.completeAssetId,
supportedProtocols = event.supportedProtocols?.toDao() ?: persistedEntity.supportedProtocols
)
}
}
override fun fromUserUpdateEventToPartialUserEntity(event: Event.User.Update): PartialUserEntity =
PartialUserEntity(
email = event.email,
name = event.name,
handle = event.handle,
accentId = event.accentId,
previewAssetId = event.previewAssetId?.let { QualifiedIDEntity(it, event.userId.domain) },
completeAssetId = event.completeAssetId?.let { QualifiedIDEntity(it, event.userId.domain) },
supportedProtocols = event.supportedProtocols?.toDao()
)

/**
* Default values and marked as [UserEntity.hasIncompleteMetadata] = true.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.id.IdMapper
import com.wire.kalium.logic.data.id.NetworkQualifiedId
import com.wire.kalium.logic.data.id.QualifiedID
import com.wire.kalium.logic.data.id.QualifiedIdMapper
import com.wire.kalium.logic.data.id.toApi
import com.wire.kalium.logic.data.id.toDao
import com.wire.kalium.logic.data.id.toModel
Expand Down Expand Up @@ -149,7 +148,6 @@ internal class UserDataSource internal constructor(
private val userDetailsApi: UserDetailsApi,
private val sessionRepository: SessionRepository,
private val selfUserId: UserId,
private val qualifiedIdMapper: QualifiedIdMapper,
private val selfTeamIdProvider: SelfTeamIdProvider,
private val idMapper: IdMapper = MapperProvider.idMapper(),
private val userMapper: UserMapper = MapperProvider.userMapper(),
Expand Down Expand Up @@ -177,7 +175,7 @@ internal class UserDataSource internal constructor(
updateSelfUserProviderAccountInfo(userDTO)
.map { userMapper.fromSelfUserDtoToUserEntity(userDTO).copy(connectionStatus = ConnectionEntity.State.ACCEPTED) }
.flatMap { userEntity ->
wrapStorageRequest { userDAO.insertUser(userEntity) }
wrapStorageRequest { userDAO.upsertUser(userEntity) }
.flatMap {
wrapStorageRequest { metadataDAO.insertValue(Json.encodeToString(userEntity.id), SELF_USER_ID_KEY) }
}
Expand Down Expand Up @@ -244,9 +242,7 @@ internal class UserDataSource internal constructor(
}

private suspend fun persistIncompleteUsers(usersFailed: List<NetworkQualifiedId>) = wrapStorageRequest {
usersFailed.map { userMapper.fromFailedUserToEntity(it) }.forEach {
userDAO.insertUser(it)
}
userDAO.insertOrIgnoreUsers(usersFailed.map { userMapper.fromFailedUserToEntity(it) })
}

private suspend fun persistUsers(listUserProfileDTO: List<UserProfileDTO>) = wrapStorageRequest {
Expand All @@ -256,7 +252,7 @@ internal class UserDataSource internal constructor(
.filter { userProfileDTO -> isTeamMember(selfUserTeamId, userProfileDTO, selfUserDomain) }
val otherUsers = listUserProfileDTO
.filter { userProfileDTO -> !isTeamMember(selfUserTeamId, userProfileDTO, selfUserDomain) }
userDAO.upsertTeamMembers(
userDAO.upsertUsers(
teamMembers.map { userProfileDTO ->
userMapper.fromUserProfileDtoToUserEntity(
userProfile = userProfileDTO,
Expand Down Expand Up @@ -347,7 +343,7 @@ internal class UserDataSource internal constructor(
.map { userMapper.fromUpdateRequestToDaoModel(user, updateRequest) }
.flatMap { userEntity ->
wrapStorageRequest {
userDAO.updateUser(userEntity)
userDAO.upsertUser(userEntity)
}.map { userMapper.fromUserEntityToSelfUser(userEntity) }
}
}
Expand Down Expand Up @@ -450,10 +446,13 @@ internal class UserDataSource internal constructor(
}

override suspend fun updateUserFromEvent(event: Event.User.Update): Either<CoreFailure, Unit> = wrapStorageRequest {
val userId = qualifiedIdMapper.fromStringToQualifiedID(event.userId)
val user =
userDAO.getUserByQualifiedID(userId.toDao()).firstOrNull() ?: return Either.Left(StorageFailure.DataNotFound)
userDAO.updateUser(userMapper.fromUserUpdateEventToUserEntity(event, user))
userDAO.updateUser(event.userId.toDao(), userMapper.fromUserUpdateEventToPartialUserEntity(event))
}.flatMap { updated ->
if (!updated) {
Either.Left(StorageFailure.DataNotFound)
} else {
Either.Right(Unit)
}
}

override suspend fun removeUser(userId: UserId): Either<CoreFailure, Unit> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ internal object MapperProvider {
fun availabilityStatusMapper(): AvailabilityStatusMapper = AvailabilityStatusMapperImpl()
fun connectionStateMapper(): ConnectionStateMapper = ConnectionStateMapperImpl()
fun userMapper(): UserMapper = UserMapperImpl(
idMapper(), availabilityStatusMapper(), connectionStateMapper(), userTypeEntityMapper()
idMapper(), availabilityStatusMapper(), connectionStateMapper()
)

fun userTypeMapper(): DomainUserTypeMapper = DomainUserTypeMapperImpl()
Expand Down Expand Up @@ -135,11 +135,12 @@ internal object MapperProvider {
fun sendMessageFailureMapper(): SendMessageFailureMapper = SendMessageFailureMapperImpl()
fun assetMapper(): AssetMapper = AssetMapperImpl()
fun encryptionAlgorithmMapper(): EncryptionAlgorithmMapper = EncryptionAlgorithmMapper()
fun eventMapper(): EventMapper = EventMapper(
fun eventMapper(selfUserId: UserId): EventMapper = EventMapper(
memberMapper(),
connectionMapper(),
featureConfigMapper(),
conversationRoleMapper(),
selfUserId,
receiptModeMapper(),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,6 @@ class UserSessionScope internal constructor(
authenticatedNetworkContainer.userDetailsApi,
globalScope.sessionRepository,
userId,
qualifiedIdMapper,
selfTeamId
)

Expand Down Expand Up @@ -1007,7 +1006,7 @@ class UserSessionScope internal constructor(

private val eventRepository: EventRepository
get() = EventDataSource(
authenticatedNetworkContainer.notificationApi, userStorage.database.metadataDAO, clientIdProvider
authenticatedNetworkContainer.notificationApi, userStorage.database.metadataDAO, clientIdProvider, userId
)

private val mlsMigrator: MLSMigrator
Expand Down
Loading

0 comments on commit 723dd25

Please sign in to comment.