Skip to content

Commit 467908b

Browse files
committed
database: add awaitWhileOnline when persistence disabled
1 parent 7ae508b commit 467908b

File tree

1 file changed

+66
-16
lines changed
  • firebase-database/src/androidMain/kotlin/dev/teamhub/firebase/database

1 file changed

+66
-16
lines changed

firebase-database/src/androidMain/kotlin/dev/teamhub/firebase/database/database.kt

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dev.teamhub.firebase.database
22

3+
import com.google.android.gms.tasks.Task
34
import com.google.firebase.database.Logger
45
import com.google.firebase.database.ServerValue
56
import com.google.firebase.database.ValueEventListener
@@ -8,11 +9,31 @@ import dev.teamhub.firebase.FirebaseApp
89
import dev.teamhub.firebase.decode
910
import dev.teamhub.firebase.encode
1011
import kotlinx.coroutines.channels.awaitClose
12+
import kotlinx.coroutines.coroutineScope
1113
import kotlinx.coroutines.flow.callbackFlow
14+
import kotlinx.coroutines.flow.conflate
15+
import kotlinx.coroutines.flow.filter
16+
import kotlinx.coroutines.flow.produceIn
17+
import kotlinx.coroutines.selects.select
18+
import kotlinx.coroutines.tasks.asDeferred
1219
import kotlinx.coroutines.tasks.await
1320
import kotlinx.serialization.DeserializationStrategy
1421
import kotlinx.serialization.SerializationStrategy
1522

23+
suspend fun <T> Task<T>.awaitWhileOnline(): T = coroutineScope {
24+
val notConnected = Firebase.database
25+
.reference(".info/connected")
26+
.snapshots
27+
.filter { !it.value<Boolean>() }
28+
.conflate()
29+
.produceIn(this)
30+
31+
select<T> {
32+
asDeferred().onAwait { it }
33+
notConnected.onReceive { throw DatabaseException("Database not connected") }
34+
}
35+
}
36+
1637
actual val Firebase.database
1738
get() = FirebaseDatabase(com.google.firebase.database.FirebaseDatabase.getInstance())
1839

@@ -26,18 +47,26 @@ actual fun Firebase.database(app: FirebaseApp, url: String) =
2647
FirebaseDatabase(com.google.firebase.database.FirebaseDatabase.getInstance(app.android, url))
2748

2849
actual class FirebaseDatabase internal constructor(val android: com.google.firebase.database.FirebaseDatabase) {
29-
actual fun reference(path: String) = DatabaseReference(android.getReference(path))
3050

31-
actual fun setPersistenceEnabled(enabled: Boolean) = android.setPersistenceEnabled(enabled)
51+
private var persistenceEnabled = true
52+
53+
actual fun reference(path: String) =
54+
DatabaseReference(android.getReference(path), persistenceEnabled)
55+
56+
actual fun setPersistenceEnabled(enabled: Boolean) =
57+
android.setPersistenceEnabled(enabled).also { persistenceEnabled = enabled }
3258

3359
actual fun setLoggingEnabled(enabled: Boolean) =
3460
android.setLogLevel(Logger.Level.DEBUG.takeIf { enabled } ?: Logger.Level.NONE)
3561
}
3662

37-
actual class DatabaseReference internal constructor(val android: com.google.firebase.database.DatabaseReference) {
63+
actual class DatabaseReference internal constructor(
64+
val android: com.google.firebase.database.DatabaseReference,
65+
val persistenceEnabled: Boolean
66+
) {
3867

39-
actual fun push() = DatabaseReference(android.push())
40-
actual fun onDisconnect() = OnDisconnect(android.onDisconnect())
68+
actual fun push() = DatabaseReference(android.push(), persistenceEnabled)
69+
actual fun onDisconnect() = OnDisconnect(android.onDisconnect(), persistenceEnabled)
4170

4271
actual val snapshots get() = callbackFlow {
4372
val listener = object : ValueEventListener {
@@ -53,16 +82,23 @@ actual class DatabaseReference internal constructor(val android: com.google.fire
5382
awaitClose { android.removeEventListener(listener) }
5483
}
5584

56-
actual suspend fun setValue(value: Any?) =
57-
android.setValue(encode(value)).await().run { Unit }
85+
actual suspend fun setValue(value: Any?) = android.setValue(encode(value))
86+
.run { if(persistenceEnabled) await() else awaitWhileOnline() }
87+
.run { Unit }
5888

5989
actual suspend inline fun <reified T> setValue(strategy: SerializationStrategy<T>, value: T) =
60-
android.setValue(encode(strategy, value)).await().run { Unit }
90+
android.setValue(encode(strategy, value))
91+
.run { if(persistenceEnabled) await() else awaitWhileOnline() }
92+
.run { Unit }
6193

6294
actual suspend fun updateChildren(update: Map<String, Any?>) =
63-
android.updateChildren(update.mapValues { (_, it) -> encode(value = it) }).await().run { Unit }
95+
android.updateChildren(update.mapValues { (_, it) -> encode(value = it) })
96+
.run { if(persistenceEnabled) await() else awaitWhileOnline() }
97+
.run { Unit }
6498

65-
actual suspend fun removeValue() = android.removeValue().await().run { Unit }
99+
actual suspend fun removeValue() = android.removeValue()
100+
.run { if(persistenceEnabled) await() else awaitWhileOnline() }
101+
.run { Unit }
66102
}
67103

68104
@Suppress("UNCHECKED_CAST")
@@ -80,19 +116,33 @@ actual class DataSnapshot internal constructor(val android: com.google.firebase.
80116
actual val children: Iterable<DataSnapshot> get() = android.children.map { DataSnapshot(it) }
81117
}
82118

83-
actual class OnDisconnect internal constructor(val android: com.google.firebase.database.OnDisconnect) {
119+
actual class OnDisconnect internal constructor(
120+
val android: com.google.firebase.database.OnDisconnect,
121+
val persistenceEnabled: Boolean
122+
) {
123+
124+
actual suspend fun removeValue() = android.removeValue()
125+
.run { if(persistenceEnabled) await() else awaitWhileOnline() }
126+
.run { Unit }
84127

85-
actual suspend fun removeValue() = android.removeValue().await().run { Unit }
86-
actual suspend fun cancel() = android.cancel().await().run { Unit }
128+
actual suspend fun cancel() = android.cancel()
129+
.run { if(persistenceEnabled) await() else awaitWhileOnline() }
130+
.run { Unit }
87131

88132
actual suspend inline fun <reified T : Any> setValue(value: T) =
89-
android.setValue(encode(value = value)).await().run { Unit }
133+
android.setValue(encode(value = value))
134+
.run { if(persistenceEnabled) await() else awaitWhileOnline() }
135+
.run { Unit }
90136

91137
actual suspend inline fun <reified T> setValue(strategy: SerializationStrategy<T>, value: T) =
92-
android.setValue(encode(strategy, value)).await().run { Unit }
138+
android.setValue(encode(strategy, value))
139+
.run { if(persistenceEnabled) await() else awaitWhileOnline() }
140+
.run { Unit}
93141

94142
actual suspend fun updateChildren(update: Map<String, Any?>) =
95-
android.updateChildren(update.mapValues { (_, it) -> encode(value = it) }).await().run { Unit }
143+
android.updateChildren(update.mapValues { (_, it) -> encode(value = it) })
144+
.run { if(persistenceEnabled) await() else awaitWhileOnline() }
145+
.run { Unit }
96146
}
97147

98148
actual typealias DatabaseException = com.google.firebase.database.DatabaseException

0 commit comments

Comments
 (0)