Skip to content

Commit b5a0b30

Browse files
Add runTransaction methods for jvm, ios and js
1 parent 63d290a commit b5a0b30

File tree

3 files changed

+64
-4
lines changed
  • firebase-database/src
    • androidMain/kotlin/dev/gitlive/firebase/database
    • iosMain/kotlin/dev/gitlive/firebase/database
    • jsMain/kotlin/dev/gitlive/firebase/database

3 files changed

+64
-4
lines changed

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

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,27 @@
55
package dev.gitlive.firebase.database
66

77
import com.google.android.gms.tasks.Task
8-
import com.google.firebase.database.ChildEventListener
9-
import com.google.firebase.database.Logger
8+
import com.google.firebase.database.*
109
import com.google.firebase.database.ServerValue
11-
import com.google.firebase.database.ValueEventListener
1210
import dev.gitlive.firebase.Firebase
1311
import dev.gitlive.firebase.FirebaseApp
1412
import dev.gitlive.firebase.database.ChildEvent.Type
1513
import dev.gitlive.firebase.decode
1614
import dev.gitlive.firebase.safeOffer
15+
import kotlinx.coroutines.CompletableDeferred
1716
import kotlinx.coroutines.FlowPreview
1817
import kotlinx.coroutines.channels.awaitClose
1918
import kotlinx.coroutines.coroutineScope
2019
import kotlinx.coroutines.flow.Flow
2120
import kotlinx.coroutines.flow.callbackFlow
2221
import kotlinx.coroutines.flow.filter
2322
import kotlinx.coroutines.flow.produceIn
23+
import kotlinx.coroutines.runBlocking
2424
import kotlinx.coroutines.selects.select
2525
import kotlinx.coroutines.tasks.asDeferred
2626
import kotlinx.coroutines.tasks.await
2727
import kotlinx.serialization.DeserializationStrategy
28+
import kotlinx.serialization.KSerializer
2829
import kotlinx.serialization.SerializationStrategy
2930

3031
@PublishedApi
@@ -188,8 +189,30 @@ actual class DatabaseReference internal constructor(
188189
actual suspend fun removeValue() = android.removeValue()
189190
.run { if(persistenceEnabled) await() else awaitWhileOnline() }
190191
.run { Unit }
191-
}
192192

193+
actual suspend fun <T> runTransaction(strategy: KSerializer<T>, transactionUpdate: (currentData: T) -> T): DataSnapshot {
194+
val deferred = CompletableDeferred<Result<DataSnapshot>>()
195+
android.runTransaction(object : Transaction.Handler {
196+
197+
override fun doTransaction(currentData: MutableData) =
198+
Transaction.success(transactionUpdate(decode(strategy, currentData)) as MutableData)
199+
200+
override fun onComplete(
201+
error: DatabaseError?,
202+
committed: Boolean,
203+
snapshot: com.google.firebase.database.DataSnapshot?
204+
) {
205+
if (error == null && snapshot != null) {
206+
deferred.complete(Result.success(DataSnapshot(snapshot)))
207+
} else {
208+
deferred.complete(Result.failure(Throwable(error?.message)))
209+
}
210+
}
211+
212+
})
213+
return deferred.await().getOrThrow()
214+
}
215+
}
193216
@Suppress("UNCHECKED_CAST")
194217
actual class DataSnapshot internal constructor(val android: com.google.firebase.database.DataSnapshot) {
195218

firebase-database/src/iosMain/kotlin/dev/gitlive/firebase/database/database.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import kotlinx.coroutines.flow.filter
2222
import kotlinx.coroutines.flow.produceIn
2323
import kotlinx.coroutines.selects.select
2424
import kotlinx.serialization.DeserializationStrategy
25+
import kotlinx.serialization.KSerializer
2526
import kotlinx.serialization.SerializationStrategy
2627
import platform.Foundation.*
2728
import kotlin.collections.component1
@@ -156,6 +157,24 @@ actual class DatabaseReference internal constructor(
156157
actual suspend fun removeValue() {
157158
ios.await(persistenceEnabled) { removeValueWithCompletionBlock(it) }
158159
}
160+
161+
actual suspend fun <T> runTransaction(strategy: KSerializer<T>, transactionUpdate: (currentData: T) -> T): DataSnapshot {
162+
val deferred = CompletableDeferred<Result<DataSnapshot>>()
163+
ios.runTransactionBlock(
164+
block = { firMutableData ->
165+
FIRTransactionResult.successWithValue(transactionUpdate(decode(strategy, firMutableData)) as FIRMutableData)
166+
},
167+
andCompletionBlock = { error, _, snapshot ->
168+
if (error == null) {
169+
deferred.complete(Result.success(DataSnapshot(snapshot!!)))
170+
} else {
171+
deferred.complete(Result.failure(Throwable(error.localizedDescription)))
172+
}
173+
},
174+
withLocalEvents = false
175+
)
176+
return deferred.await().getOrThrow()
177+
}
159178
}
160179

161180
@Suppress("UNCHECKED_CAST")

firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import kotlinx.coroutines.flow.filter
1212
import kotlinx.coroutines.flow.produceIn
1313
import kotlinx.coroutines.selects.select
1414
import kotlinx.serialization.DeserializationStrategy
15+
import kotlinx.serialization.KSerializer
1516
import kotlinx.serialization.SerializationStrategy
1617
import kotlin.js.Promise
1718

@@ -127,6 +128,23 @@ actual class DatabaseReference internal constructor(override val js: firebase.da
127128

128129
actual suspend fun <T> setValue(strategy: SerializationStrategy<T>, value: T, encodeDefaults: Boolean) =
129130
rethrow { js.set(encode(strategy, value, encodeDefaults)).awaitWhileOnline() }
131+
132+
actual suspend fun <T> runTransaction(strategy: KSerializer<T>, transactionUpdate: (currentData: T) -> T): DataSnapshot {
133+
val deferred = CompletableDeferred<Result<DataSnapshot>>()
134+
js.runTransaction(
135+
transactionUpdate,
136+
{ error, _, snapshot ->
137+
if (error != null) {
138+
deferred.complete(Result.success(DataSnapshot(snapshot!!)))
139+
} else {
140+
deferred.complete(Result.failure(Throwable(error?.message)))
141+
}
142+
},
143+
applyLocally = false
144+
).await()
145+
return deferred.await().getOrThrow()
146+
}
147+
130148
}
131149

132150
actual class DataSnapshot internal constructor(val js: firebase.database.DataSnapshot) {

0 commit comments

Comments
 (0)