개발하는 두더지

[Kotlin]coroutine, firestore java.lang.IllegalStateException: Already resumed, but proposed with update 에러 처리 본문

Kotlin

[Kotlin]coroutine, firestore java.lang.IllegalStateException: Already resumed, but proposed with update 에러 처리

덜지 2019. 3. 5. 11:29

coroutine, firestore java.lang.IllegalStateException: Already resumed, but proposed with update 에러 처리 방법

firestore의 API인 addSnapshotListener를 이용하면 document나 collection에 새로운 아이템이 생기면 바로 이벤트가 트리거되어 실시간으로 데이터를 받을 수 있습니다. 이때 runBlocking, launch로 coroutine을 이용하고 있었다면 아래와 같은 에러가 발생합니다.

java.lang.IllegalStateException: Already resumed, but proposed with update  
at kotlinx.coroutines.CancellableContinuationImpl.alreadyResumedError(CancellableContinuationImpl.kt:244)  
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:239)  
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:168)

Channel은 stream을 전송할 수 있는 API 입니다. 검색해보면 알 수 있듯이 BlockingQueue와 유사합니다.

put 대신 send , take 대신 receive 메서드를 사용하는 것이 차이점입니다.

override suspend fun getComments(post\_id: String): ReceiveChannel<List\> {  
val channel = Channel<List\>()

return suspendCancellableCoroutine { continuation \->  


fireStore.collection(POST\_COLLECTION).whereEqualTo(POST\_DOCUMENT.PARENT\_POST\_NO, post\_id).  
addSnapshotListener { querySnapshot, firebaseFirestoreException ->

if (querySnapshot == null) {  
channel.close()  
return@addSnapshotListener  
}  
firebaseFirestoreException?.let {  
channel.close(it)  
return@addSnapshotListener  
}

val commentDTOs = arrayListOf()  
for(snapshot in querySnapshot.documents) {  
val item = snapshot.toObject(CommentDTO::class.java)  
if(item?.parent\_post\_no == post\_id) {  
commentDTOs.add(item)  
}  
}
        channel.sendBlocking(commentDTOs)  
    }  

continuation.resume(channel)  
}  
}  

채널을 만들고 sendBlocking으로 전달하면 됩니다..

채널을 받는 쪽에선 아래 코드처럼 receive() 로 받거나 iterator로 받으면 됩니다.

suspend fun loadComments(post\_id: String) {  
val channel = dataSource.getComments(post\_id)  
for(list in channel) {  
println("channel size")  
commentDTOLiveData.value = list  
}  
}

참고

https://github.com/brotoo25/firestore-coroutines/blob/master/firestore-coroutines/src/main/kotlin/com/kiwimob/firestore/coroutines/DocumentCoroutines.kt

Comments