Skip to content

Commit

Permalink
🔀 #94 from boostcampwm-2022/fix/coroutineScope
Browse files Browse the repository at this point in the history
Data Layer에서 ViewModelScope를 사용하지 않도록 변경
  • Loading branch information
soopeach authored Dec 12, 2022
2 parents fcddadd + ed4648e commit 4b85567
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class RunningHistoryLocalDataSourceImpl @Inject constructor(
}

override suspend fun saveRunningHistory(runningHistoryEntity: RunningHistoryEntity): Result<RunningHistory> {
return kotlin.runCatching {
return runCatching {
runningHistoryDao.addRunningHistory(runningHistoryEntity)
runningHistoryEntity.toRunningHistory()
}
Expand Down
16 changes: 16 additions & 0 deletions data/src/main/java/com/whyranoid/data/di/CoroutineModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.whyranoid.data.di

import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.Dispatchers

@Module
@InstallIn(SingletonComponent::class)
class CoroutineModule {

@Provides
@IODispatcher
fun provideIODispatcher() = Dispatchers.IO
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.whyranoid.data.di

import javax.inject.Qualifier

@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class IODispatcher
40 changes: 16 additions & 24 deletions data/src/main/java/com/whyranoid/data/group/GroupDataSourceImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.whyranoid.data.group

import com.google.firebase.firestore.FieldValue
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ktx.snapshots
import com.whyranoid.data.constant.CollectionId.GROUPS_COLLECTION
import com.whyranoid.data.constant.CollectionId.USERS_COLLECTION
import com.whyranoid.data.constant.FieldId.GROUP_INTRODUCE
Expand All @@ -17,10 +18,9 @@ import com.whyranoid.domain.model.GroupInfo
import com.whyranoid.domain.model.MoGakRunException
import com.whyranoid.domain.model.Rule
import com.whyranoid.domain.model.toRule
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.tasks.await
import java.util.*
Expand Down Expand Up @@ -177,31 +177,23 @@ class GroupDataSourceImpl @Inject constructor(
}

private fun getGroupInfoResponse(groupId: String): Flow<GroupInfoResponse> {
return callbackFlow {
db.collection(GROUPS_COLLECTION)
.document(groupId)
.addSnapshotListener { documentSnapshot, _ ->
trySend(
documentSnapshot?.toObject(GroupInfoResponse::class.java)
?: throw MoGakRunException.FileNotFoundedException
)
}
awaitClose()
}
return db.collection(GROUPS_COLLECTION)
.document(groupId)
.snapshots()
.map { documentSnapshot ->
documentSnapshot.toObject(GroupInfoResponse::class.java)
?: throw MoGakRunException.FileNotFoundedException
}
}

private fun getUserResponse(uid: String): Flow<UserResponse> {
return callbackFlow {
db.collection(USERS_COLLECTION)
.document(uid)
.addSnapshotListener { documentSnapshot, _ ->
trySend(
documentSnapshot?.toObject(UserResponse::class.java)
?: throw MoGakRunException.FileNotFoundedException
)
}
awaitClose()
}
return db.collection(USERS_COLLECTION)
.document(uid)
.snapshots()
.map { documentSnapshot ->
documentSnapshot.toObject(UserResponse::class.java)
?: throw MoGakRunException.FileNotFoundedException
}
}

override suspend fun isDuplicatedGroupName(groupName: String): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import com.whyranoid.domain.model.GroupNotification
import com.whyranoid.domain.model.Rule
import com.whyranoid.domain.model.RunningHistory
import com.whyranoid.domain.repository.GroupRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

Expand All @@ -21,7 +20,7 @@ class GroupRepositoryImpl @Inject constructor(
return userDataSource.getMyGroupList(uid)
}

override fun getMyGroupListFlow(uid: String, coroutineScope: CoroutineScope) = userDataSource.getMyGroupListFlow(uid, coroutineScope)
override fun getMyGroupListFlow(uid: String) = userDataSource.getMyGroupListFlow(uid)

override suspend fun updateGroupInfo(
groupId: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.whyranoid.data.groupnotification

import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ktx.snapshots
import com.whyranoid.data.constant.CollectionId.FINISH_NOTIFICATION
import com.whyranoid.data.constant.CollectionId.GROUP_NOTIFICATIONS_COLLECTION
import com.whyranoid.data.constant.CollectionId.RUNNING_HISTORY_COLLECTION
Expand All @@ -12,14 +13,14 @@ import com.whyranoid.domain.model.FinishNotification
import com.whyranoid.domain.model.GroupNotification
import com.whyranoid.domain.model.RunningHistory
import com.whyranoid.domain.model.StartNotification
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.flattenMerge
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.withContext
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.tasks.await
import java.util.UUID
import javax.inject.Inject

Expand All @@ -40,10 +41,10 @@ class GroupNotificationDataSourceImpl @Inject constructor(

private fun getGroupStartNotifications(groupId: String): Flow<List<GroupNotification>> =
callbackFlow {
db.collection(GROUP_NOTIFICATIONS_COLLECTION)
val registration = db.collection(GROUP_NOTIFICATIONS_COLLECTION)
.document(groupId)
.collection(START_NOTIFICATION)
.addSnapshotListener { snapshot, error ->
.addSnapshotListener { snapshot, _ ->
val startNotificationList = mutableListOf<GroupNotification>()
snapshot?.forEach { document ->
val startNotification =
Expand All @@ -53,58 +54,59 @@ class GroupNotificationDataSourceImpl @Inject constructor(
trySend(startNotificationList)
}

awaitClose()
awaitClose {
registration.remove()
}
}

private fun getGroupFinishNotifications(groupId: String): Flow<List<GroupNotification>> =
callbackFlow {
db.collection(GROUP_NOTIFICATIONS_COLLECTION)
.document(groupId)
.collection(FINISH_NOTIFICATION)
.addSnapshotListener { snapshot, error ->
val finishNotificationList = mutableListOf<GroupNotification>()
snapshot?.forEach { document ->
val finishNotificationResponse =
document.toObject(FinishNotificationResponse::class.java)
private fun getGroupFinishNotifications(groupId: String): Flow<List<GroupNotification>> {
return db.collection(GROUP_NOTIFICATIONS_COLLECTION)
.document(groupId)
.collection(FINISH_NOTIFICATION)
.snapshots()
.map { snapshot ->
val finishNotificationList = mutableListOf<GroupNotification>()

finishNotificationResponse.let { finishNotificationResponse ->
db.collection(RUNNING_HISTORY_COLLECTION)
.document(finishNotificationResponse.historyId)
.get()
.addOnSuccessListener {
val runningHistory = it.toObject(RunningHistory::class.java)
snapshot.forEach { document ->
val finishNotificationResponse =
document.toObject(FinishNotificationResponse::class.java)

runningHistory?.let {
finishNotificationList.add(
FinishNotification(
uid = finishNotificationResponse.uid,
runningHistory = runningHistory
)
)
}
trySend(finishNotificationList)
}
finishNotificationResponse.let { finishNotification ->
getRunningHistory(finishNotification.historyId)?.let { runningHistory ->
finishNotificationList.add(
FinishNotification(
uid = finishNotification.uid,
runningHistory = runningHistory
)
)
}
}
}
finishNotificationList
}
}

awaitClose()
}
// TODO : 예외처리
private suspend fun getRunningHistory(historyId: String): RunningHistory? {
return db.collection(RUNNING_HISTORY_COLLECTION)
.document(historyId)
.get()
.await()
.toObject(RunningHistory::class.java)
}

override suspend fun notifyRunningStart(uid: String, groupIdList: List<String>) {
withContext(Dispatchers.IO) {
groupIdList.forEach { groupId ->
db.collection(GROUP_NOTIFICATIONS_COLLECTION)
.document(groupId)
.collection(START_NOTIFICATION)
.document(UUID.randomUUID().toString())
.set(
StartNotification(
startedAt = System.currentTimeMillis(),
uid = uid
)
groupIdList.forEach { groupId ->
db.collection(GROUP_NOTIFICATIONS_COLLECTION)
.document(groupId)
.collection(START_NOTIFICATION)
.document(UUID.randomUUID().toString())
.set(
StartNotification(
startedAt = System.currentTimeMillis(),
uid = uid
)
}
)
}
}

Expand All @@ -113,19 +115,17 @@ class GroupNotificationDataSourceImpl @Inject constructor(
runningHistory: RunningHistory,
groupIdList: List<String>
) {
withContext(Dispatchers.IO) {
groupIdList.forEach { groupId ->
db.collection(GROUP_NOTIFICATIONS_COLLECTION)
.document(groupId)
.collection(FINISH_NOTIFICATION)
.document(UUID.randomUUID().toString())
.set(
FinishNotificationResponse(
uid = uid,
historyId = runningHistory.historyId
)
groupIdList.forEach { groupId ->
db.collection(GROUP_NOTIFICATIONS_COLLECTION)
.document(groupId)
.collection(FINISH_NOTIFICATION)
.document(UUID.randomUUID().toString())
.set(
FinishNotificationResponse(
uid = uid,
historyId = runningHistory.historyId
)
}
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import kotlin.coroutines.resume
class RunnerDataSourceImpl(private val db: FirebaseFirestore) : RunnerDataSource {

override fun getCurrentRunnerCount(): Flow<Int> = callbackFlow {
db.collection(CollectionId.RUNNERS_COLLECTION)
val registration = db.collection(CollectionId.RUNNERS_COLLECTION)
.document(CollectionId.RUNNERS_ID)
.addSnapshotListener { snapshot, _ ->
snapshot?.let {
Expand All @@ -21,7 +21,9 @@ class RunnerDataSourceImpl(private val db: FirebaseFirestore) : RunnerDataSource
}
}

awaitClose()
awaitClose {
registration.remove()
}
}

override suspend fun startRunning(uid: String): Boolean {
Expand Down
3 changes: 1 addition & 2 deletions data/src/main/java/com/whyranoid/data/user/UserDataSource.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package com.whyranoid.data.user

import com.whyranoid.domain.model.GroupInfo
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow

interface UserDataSource {

suspend fun getMyGroupList(uid: String): Result<List<GroupInfo>>

fun getMyGroupListFlow(uid: String, coroutineScope: CoroutineScope): Flow<List<GroupInfo>>
fun getMyGroupListFlow(uid: String): Flow<List<GroupInfo>>
}
23 changes: 15 additions & 8 deletions data/src/main/java/com/whyranoid/data/user/UserDataSourceImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import com.whyranoid.data.constant.CollectionId.USERS_COLLECTION
import com.whyranoid.data.constant.Exceptions.NO_GROUP_EXCEPTION
import com.whyranoid.data.constant.Exceptions.NO_JOINED_GROUP_EXCEPTION
import com.whyranoid.data.constant.Exceptions.NO_USER_EXCEPTION
import com.whyranoid.data.di.IODispatcher
import com.whyranoid.data.model.GroupInfoResponse
import com.whyranoid.data.model.UserResponse
import com.whyranoid.data.model.toGroupInfo
import com.whyranoid.data.model.toUser
import com.whyranoid.domain.model.GroupInfo
import com.whyranoid.domain.model.User
import com.whyranoid.domain.model.toRule
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
Expand All @@ -22,7 +25,9 @@ import kotlinx.coroutines.tasks.await
import javax.inject.Inject

class UserDataSourceImpl @Inject constructor(
private val db: FirebaseFirestore
private val db: FirebaseFirestore,
@IODispatcher
private val dispatcher: CoroutineDispatcher
) : UserDataSource {

override suspend fun getMyGroupList(uid: String): Result<List<GroupInfo>> {
Expand Down Expand Up @@ -67,27 +72,29 @@ class UserDataSourceImpl @Inject constructor(

// TODO: 예외처리
override fun getMyGroupListFlow(
uid: String,
coroutineScope: CoroutineScope
uid: String
): Flow<List<GroupInfo>> = callbackFlow {
db.collection(USERS_COLLECTION)
val coroutineScope = CoroutineScope(dispatcher)
val registration = db.collection(USERS_COLLECTION)
.document(uid)
.addSnapshotListener { documentSnapshot, _ ->
val myGroupInfoList = mutableListOf<GroupInfo>()
val joinedGroupList =
documentSnapshot?.toObject(UserResponse::class.java)?.joinedGroupList

joinedGroupList?.forEach { groupId ->

coroutineScope.launch {
coroutineScope.launch {
joinedGroupList?.forEach { groupId ->
val groupInfo = getGroupInfo(groupId)
myGroupInfoList.add(groupInfo)
trySend(myGroupInfoList)
}
}
}

awaitClose()
awaitClose {
coroutineScope.cancel()
registration.remove()
}
}

// TODO : 예외 처리
Expand Down
Loading

0 comments on commit 4b85567

Please sign in to comment.