Skip to content

Commit

Permalink
Transaction Durability and Write Transaction Mutual Exclusion (#137)
Browse files Browse the repository at this point in the history
* Expose transaction durability, fix write transaction exclusion

* Durability jsValue as extension val

* Use cheaper dummy query for mutex
  • Loading branch information
cedrickcooke committed Dec 24, 2023
1 parent eb45b5e commit 12ea9ee
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 5 deletions.
22 changes: 18 additions & 4 deletions core/src/jsMain/kotlin/Database.kt
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,12 @@ public class Database internal constructor(internal val database: IDBDatabase) {
*/
public suspend fun <T> transaction(
vararg store: String,
durability: Durability = Durability.Default,
action: suspend Transaction.() -> T,
): T = withContext(Dispatchers.Unconfined) {
@Suppress("UNCHECKED_CAST") // What a silly cast. Apparently `vararg` creates `Array<out String>` instead of `Array<String>`
val transaction = Transaction(database.transaction(store as Array<String>, "readonly"))
val transaction = Transaction(
database.transaction(arrayOf(*store), "readonly", transactionOptions(durability)),
)
val result = transaction.action()
transaction.awaitCompletion()
result
Expand All @@ -81,10 +83,18 @@ public class Database internal constructor(internal val database: IDBDatabase) {
*/
public suspend fun <T> writeTransaction(
vararg store: String,
durability: Durability = Durability.Default,
action: suspend WriteTransaction.() -> T,
): T = withContext(Dispatchers.Unconfined) {
@Suppress("UNCHECKED_CAST") // What a silly cast. Apparently `vararg` creates `Array<out String>` instead of `Array<String>`
val transaction = WriteTransaction(database.transaction(store as Array<String>, "readwrite"))
val transaction = WriteTransaction(
database.transaction(arrayOf(*store), "readwrite", transactionOptions(durability)),
)
with(transaction) {
// Force overlapping transactions to not call `action` until prior transactions complete.
objectStore(store.first())
.openKeyCursor(autoContinue = false)
.collect { it.close() }
}
val result = transaction.action()
transaction.awaitCompletion()
result
Expand All @@ -94,3 +104,7 @@ public class Database internal constructor(internal val database: IDBDatabase) {
database.close()
}
}

private fun transactionOptions(durability: Durability): dynamic = jso {
this.durability = durability.jsValue
}
19 changes: 19 additions & 0 deletions core/src/jsMain/kotlin/Durability.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.juul.indexeddb

import com.juul.indexeddb.Durability.Default
import com.juul.indexeddb.Durability.Relaxed
import com.juul.indexeddb.Durability.Strict

/** https://developer.mozilla.org/en-US/docs/Web/API/IDBTransaction/durability */
public enum class Durability {
Default,
Strict,
Relaxed,
}

internal val Durability.jsValue: String
get() = when (this) {
Default -> "default"
Strict -> "strict"
Relaxed -> "relaxed"
}
2 changes: 1 addition & 1 deletion external/src/jsMain/kotlin/IDBDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ public external class IDBDatabase : EventTarget {
public fun createObjectStore(name: String): IDBObjectStore
public fun createObjectStore(name: String, options: dynamic): IDBObjectStore
public fun deleteObjectStore(name: String)
public fun transaction(storeNames: Array<String>, mode: String): IDBTransaction
public fun transaction(storeNames: Array<String>, mode: String, options: dynamic): IDBTransaction
}

0 comments on commit 12ea9ee

Please sign in to comment.