Skip to content

Commit

Permalink
Fix deleteDatabase blocking due to open connections
Browse files Browse the repository at this point in the history
- Automatically close database connections on delete
- Handle "blocked" event in deleteDatabase
  • Loading branch information
janne-koschinski committed Jan 26, 2024
1 parent 222f3a0 commit ead7323
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 10 deletions.
19 changes: 13 additions & 6 deletions core/src/jsMain/kotlin/Database.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,21 @@ public suspend fun openDatabase(
public suspend fun deleteDatabase(name: String) {
val factory = checkNotNull(window.indexedDB) { "Your browser doesn't support IndexedDB." }
val request = factory.deleteDatabase(name)
request.onNextEvent("success", "error") { event ->
request.onNextEvent("success", "error", "blocked") { event ->
when (event.type) {
"error" -> throw ErrorEventException(event)
"error", "blocked" -> throw ErrorEventException(event)
else -> null
}
}
}

public class Database internal constructor(internal val database: IDBDatabase) {
public class Database internal constructor(database: IDBDatabase) {
internal var database: IDBDatabase? = database

init {
database.addEventListener("versionchange", { close() })
database.addEventListener("close", { close() })
}

/**
* Inside the [action] block, you must not call any `suspend` functions except for:
Expand All @@ -68,7 +74,7 @@ public class Database internal constructor(internal val database: IDBDatabase) {
action: suspend Transaction.() -> T,
): T = withContext(Dispatchers.Unconfined) {
val transaction = Transaction(
database.transaction(arrayOf(*store), "readonly", transactionOptions(durability)),
database!!.transaction(arrayOf(*store), "readonly", transactionOptions(durability)),
)
val result = transaction.action()
transaction.awaitCompletion()
Expand All @@ -87,7 +93,7 @@ public class Database internal constructor(internal val database: IDBDatabase) {
action: suspend WriteTransaction.() -> T,
): T = withContext(Dispatchers.Unconfined) {
val transaction = WriteTransaction(
database.transaction(arrayOf(*store), "readwrite", transactionOptions(durability)),
database!!.transaction(arrayOf(*store), "readwrite", transactionOptions(durability)),
)
with(transaction) {
// Force overlapping transactions to not call `action` until prior transactions complete.
Expand All @@ -101,7 +107,8 @@ public class Database internal constructor(internal val database: IDBDatabase) {
}

public fun close() {
database.close()
database?.close()
database = null
}
}

Expand Down
8 changes: 4 additions & 4 deletions core/src/jsMain/kotlin/Transaction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -300,18 +300,18 @@ public class VersionChangeTransaction internal constructor(

/** Creates an object-store that uses explicit out-of-line keys. */
public fun Database.createObjectStore(name: String): ObjectStore =
ObjectStore(database.createObjectStore(name))
ObjectStore(database!!.createObjectStore(name))

/** Creates an object-store that uses in-line keys. */
public fun Database.createObjectStore(name: String, keyPath: KeyPath): ObjectStore =
ObjectStore(database.createObjectStore(name, keyPath.toWrappedJs()))
ObjectStore(database!!.createObjectStore(name, keyPath.toWrappedJs()))

/** Creates an object-store that uses out-of-line keys with a key-generator. */
public fun Database.createObjectStore(name: String, autoIncrement: AutoIncrement): ObjectStore =
ObjectStore(database.createObjectStore(name, autoIncrement.toJs()))
ObjectStore(database!!.createObjectStore(name, autoIncrement.toJs()))

public fun Database.deleteObjectStore(name: String) {
database.deleteObjectStore(name)
database!!.deleteObjectStore(name)
}

public fun ObjectStore.createIndex(name: String, keyPath: KeyPath, unique: Boolean): Index =
Expand Down

0 comments on commit ead7323

Please sign in to comment.