Skip to content

Commit

Permalink
Implement posting thumbs-up count to firestore
Browse files Browse the repository at this point in the history
  • Loading branch information
mkeeda committed Jan 29, 2020
1 parent 67a0c93 commit 44b8b10
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ import kotlinx.coroutines.flow.Flow
interface Firestore {
fun getFavoriteSessionIds(): Flow<List<String>>
suspend fun toggleFavorite(sessionId: SessionId)
fun thumbsUp(sessionId: SessionId): Flow<Int>
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package io.github.droidkaigi.confsched2020.data.firestore.internal

import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.CollectionReference
import com.google.firebase.firestore.DocumentReference
import com.google.firebase.firestore.DocumentSnapshot
import com.google.firebase.firestore.FieldValue
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.Query
import com.google.firebase.firestore.QuerySnapshot
import com.google.firebase.firestore.Source
import io.github.droidkaigi.confsched2020.data.firestore.Firestore
import io.github.droidkaigi.confsched2020.model.SessionId
import io.github.droidkaigi.confsched2020.model.Shard
import io.github.droidkaigi.confsched2020.model.ThumbsUpCounter
import javax.inject.Inject
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
Expand All @@ -20,8 +25,13 @@ import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.tasks.await
import timber.log.Timber
import timber.log.debug
import kotlin.math.floor
import kotlin.math.sin

internal class FirestoreImpl @Inject constructor() : Firestore {
companion object {
const val NUM_SHARDS = 10
}

override fun getFavoriteSessionIds(): Flow<List<String>> {
val setupFavorites = flow {
Expand Down Expand Up @@ -63,6 +73,15 @@ internal class FirestoreImpl @Inject constructor() : Firestore {
Timber.debug { "toggleFavorite: end" }
}

override fun thumbsUp(sessionId: SessionId): Flow<Int> {
return flow {
signInIfNeeded()
val counterRef = createThumbsUpCounterIfNeeded(sessionId = sessionId, numShards = NUM_SHARDS)
incrementThumbsUpCount(counterRef)
emit(getThumbsUpCount(counterRef))
}
}

private fun getFavoritesRef(): CollectionReference {
val firebaseAuth = FirebaseAuth.getInstance()
val firebaseUserId = firebaseAuth.currentUser?.uid ?: throw RuntimeException(
Expand All @@ -83,6 +102,62 @@ internal class FirestoreImpl @Inject constructor() : Firestore {
firebaseAuth.signInAnonymously().await()
Timber.debug { "signInIfNeeded end" }
}

private suspend fun createThumbsUpCounterIfNeeded(sessionId: SessionId, numShards: Int): DocumentReference {
val firebaseAuth = FirebaseAuth.getInstance()
val firebaseUserId = firebaseAuth.currentUser?.uid ?: throw RuntimeException(
"RuntimeException"
)
val counterDocumentRef = FirebaseFirestore
.getInstance()
.collection("confsched/2020/sessions/$sessionId/thumbsup_counters")
.document(firebaseUserId)

if (counterDocumentRef.fastGet().exists()) {
Timber.debug { "createThumbsUpCounterIfNeeded counter already exists" }
return counterDocumentRef
}

counterDocumentRef.set(ThumbsUpCounter(numShards))
.continueWithTask { task ->
if (!task.isSuccessful) {
throw task.exception!!
}

val tasks = arrayListOf<Task<Void>>()

// Initialize each shard with count=0
for (i in 0 until numShards) {
val makeShard = counterDocumentRef.collection("shards")
.document(i.toString())
.set(Shard(count = 0))

tasks.add(makeShard)
}

Tasks.whenAll(tasks)
}.await()

Timber.debug { "createThumbsUpCounterIfNeeded creating counter completed" }
return counterDocumentRef
}

private fun incrementThumbsUpCount(counterRef: DocumentReference) {
val shardId = floor(Math.random() * NUM_SHARDS).toInt()
counterRef.collection("shards")
.document(shardId.toString())
.update("count", FieldValue.increment(1))
}

private suspend fun getThumbsUpCount(counterRef: DocumentReference): Int {
val shards = counterRef.collection("shards").fastGet()
var count = 0
shards.forEach { snap ->
val shard = snap.toObject(Shard::class.java)
count += shard.count
}
return count
}
}

private suspend fun DocumentReference.fastGet(): DocumentSnapshot {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package io.github.droidkaigi.confsched2020.model

data class Shard(val count: Int)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package io.github.droidkaigi.confsched2020.model

data class ThumbsUpCounter(val numShards: Int)

0 comments on commit 44b8b10

Please sign in to comment.