[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-wallet-core] 01/02: idb-bridge: only reload schema on abort when
From: |
gnunet |
Subject: |
[taler-wallet-core] 01/02: idb-bridge: only reload schema on abort when in versionchange transaction |
Date: |
Fri, 10 Jan 2025 12:06:03 +0100 |
This is an automated email from the git hooks/post-receive script.
dold pushed a commit to branch master
in repository wallet-core.
commit ebadef8ba5cb0a08055ae3cf6226e6a78a9c43c5
Author: Florian Dold <florian@dold.me>
AuthorDate: Fri Jan 10 12:05:11 2025 +0100
idb-bridge: only reload schema on abort when in versionchange transaction
---
packages/idb-bridge/src/SqliteBackend.ts | 115 ++++++++++++++++++++++---------
packages/idb-bridge/src/bridge-idb.ts | 8 ++-
2 files changed, 89 insertions(+), 34 deletions(-)
diff --git a/packages/idb-bridge/src/SqliteBackend.ts
b/packages/idb-bridge/src/SqliteBackend.ts
index cecf0794a..10dd19956 100644
--- a/packages/idb-bridge/src/SqliteBackend.ts
+++ b/packages/idb-bridge/src/SqliteBackend.ts
@@ -731,7 +731,9 @@ export class SqliteBackend implements Backend {
throw Error(
`object store ${JSON.stringify(
req.objectStoreName,
- )} not in transaction scope`,
+ )} not in transaction scope, only have ${JSON.stringify(
+ Object.keys(connInfo.storeMap),
+ )}`,
);
}
@@ -951,7 +953,6 @@ export class SqliteBackend implements Backend {
dbConn: DatabaseConnection,
objectStoreName: string,
): ObjectStoreMeta | undefined {
- // FIXME: Use cached info from the connection for this!
const connInfo = this.connectionMap.get(dbConn.connectionCookie);
if (!connInfo) {
throw Error("connection not found");
@@ -1034,7 +1035,9 @@ export class SqliteBackend implements Backend {
async _runSqlGetDatabaseVersion(
databaseName: string,
): Promise<number | undefined> {
- const versionRes = await (await
this._prep(sqlGetDatabaseVersion)).getFirst({
+ const versionRes = await (
+ await this._prep(sqlGetDatabaseVersion)
+ ).getFirst({
name: databaseName,
});
if (versionRes == undefined) {
@@ -1106,7 +1109,9 @@ export class SqliteBackend implements Backend {
connInfo: ConnectionInfo,
storeName: string,
): Promise<void> {
- const objRes = await (await
this._prep(sqlGetObjectStoreMetaByName)).getFirst({
+ const objRes = await (
+ await this._prep(sqlGetObjectStoreMetaByName)
+ ).getFirst({
name: storeName,
database_name: connInfo.databaseName,
});
@@ -1118,7 +1123,9 @@ export class SqliteBackend implements Backend {
const objectStoreKeyPath = deserializeKeyPath(
expectDbStringOrNull(objRes, "key_path"),
);
- const indexRes = await (await
this._prep(sqlGetIndexesByObjectStoreId)).getAll({
+ const indexRes = await (
+ await this._prep(sqlGetIndexesByObjectStoreId)
+ ).getAll({
object_store_id: objectStoreId,
});
if (!indexRes) {
@@ -1272,7 +1279,9 @@ export class SqliteBackend implements Backend {
const objectStoreNames = await this._loadObjectStoreNames(databaseName);
for (const storeName of objectStoreNames) {
- const objRes = await (await
this._prep(sqlGetObjectStoreMetaByName)).getFirst({
+ const objRes = await (
+ await this._prep(sqlGetObjectStoreMetaByName)
+ ).getFirst({
name: storeName,
database_name: databaseName,
});
@@ -1280,7 +1289,9 @@ export class SqliteBackend implements Backend {
throw Error("object store not found");
}
const objectStoreId = expectDbNumber(objRes, "id");
- const indexRes = await (await
this._prep(sqlGetIndexesByObjectStoreId)).getAll({
+ const indexRes = await (
+ await this._prep(sqlGetIndexesByObjectStoreId)
+ ).getAll({
object_store_id: objectStoreId,
});
if (!indexRes) {
@@ -1319,18 +1330,26 @@ export class SqliteBackend implements Backend {
await stmt.run({
index_id: indexInfo.indexId,
});
- await (await this._prep(sqlIndexDelete)).run({
+ await (
+ await this._prep(sqlIndexDelete)
+ ).run({
index_id: indexInfo.indexId,
});
}
- await (await this._prep(sqlObjectDataDeleteAll)).run({
+ await (
+ await this._prep(sqlObjectDataDeleteAll)
+ ).run({
object_store_id: objectStoreId,
});
- await (await this._prep(sqlObjectStoreDelete)).run({
+ await (
+ await this._prep(sqlObjectStoreDelete)
+ ).run({
object_store_id: objectStoreId,
});
}
- await (await this._prep(sqlDeleteDatabase)).run({
+ await (
+ await this._prep(sqlDeleteDatabase)
+ ).run({
name: databaseName,
});
await (await this._prep(sqlCommit)).run();
@@ -1425,14 +1444,20 @@ export class SqliteBackend implements Backend {
await stmt.run({
index_id: indexInfo.indexId,
});
- await (await this._prep(sqlIndexDelete)).run({
+ await (
+ await this._prep(sqlIndexDelete)
+ ).run({
index_id: indexInfo.indexId,
});
}
- await (await this._prep(sqlObjectDataDeleteAll)).run({
+ await (
+ await this._prep(sqlObjectDataDeleteAll)
+ ).run({
object_store_id: scopeInfo.objectStoreId,
});
- await (await this._prep(sqlObjectStoreDelete)).run({
+ await (
+ await this._prep(sqlObjectStoreDelete)
+ ).run({
object_store_id: scopeInfo.objectStoreId,
});
}
@@ -1469,7 +1494,9 @@ export class SqliteBackend implements Backend {
await stmt.run({
index_id: indexMeta.indexId,
});
- await (await this._prep(sqlIndexDelete)).run({
+ await (
+ await this._prep(sqlIndexDelete)
+ ).run({
index_id: indexMeta.indexId,
});
}
@@ -1516,13 +1543,17 @@ export class SqliteBackend implements Backend {
return;
}
await (await this._prep(sqlRollback)).run();
- connInfo.storeList = [];
- connInfo.storeMap.clear();
- const objectStoreNames: string[] = await this._loadObjectStoreNames(
- connInfo.databaseName,
- );
- for (const storeName of objectStoreNames) {
- await this._loadScopeInfo(connInfo, storeName);
+ if (this.txLevel === TransactionLevel.VersionChange) {
+ // Rollback also undoes schema changes, but that is only
+ // relevant in a versionchange transaction.
+ connInfo.storeList = [];
+ connInfo.storeMap.clear();
+ const objectStoreNames: string[] = await this._loadObjectStoreNames(
+ connInfo.databaseName,
+ );
+ for (const storeName of objectStoreNames) {
+ await this._loadScopeInfo(connInfo, storeName);
+ }
}
this.txLevel = TransactionLevel.None;
this.transactionMap.delete(btx.transactionCookie);
@@ -1554,7 +1585,9 @@ export class SqliteBackend implements Backend {
await this._provideObjectStore(connInfo, store);
}
if (store.nameDirty) {
- await (await this._prep(sqlRenameObjectStore)).run({
+ await (
+ await this._prep(sqlRenameObjectStore)
+ ).run({
object_store_id: store.objectStoreId,
name: store.currentName,
});
@@ -1568,7 +1601,9 @@ export class SqliteBackend implements Backend {
await this._provideIndex(connInfo, store, indexMeta);
}
if (indexMeta.nameDirty) {
- await (await this._prep(sqlRenameIndex)).run({
+ await (
+ await this._prep(sqlRenameIndex)
+ ).run({
index_id: indexMeta.indexId,
name: indexMeta.currentName,
});
@@ -1594,7 +1629,9 @@ export class SqliteBackend implements Backend {
throw Error("invalid state");
}
- const runRes = await (await this._prep(sqlCreateObjectStore)).run({
+ const runRes = await (
+ await this._prep(sqlCreateObjectStore)
+ ).run({
name: storeMeta.currentName,
key_path: serializeKeyPath(storeMeta.keyPath),
auto_increment: storeMeta.autoIncrement ? 1 : 0,
@@ -1661,7 +1698,9 @@ export class SqliteBackend implements Backend {
if (storeMeta.objectStoreId == null) {
throw Error("invariant failed");
}
- const res = await (await this._prep(sqlCreateIndex)).run({
+ const res = await (
+ await this._prep(sqlCreateIndex)
+ ).run({
object_store_id: storeMeta.objectStoreId,
name: indexMeta.currentName,
key_path: serializeKeyPath(indexMeta.keyPath),
@@ -1672,7 +1711,9 @@ export class SqliteBackend implements Backend {
// FIXME: We can't use an iterator here, as it's not allowed to
// execute a write statement while the iterator executes.
// Maybe do multiple selects instead of loading everything into memory?
- const keyRowsRes = await (await this._prep(sqlObjectDataGetAll)).getAll({
+ const keyRowsRes = await (
+ await this._prep(sqlObjectDataGetAll)
+ ).getAll({
object_store_id: storeMeta.objectStoreId,
});
@@ -1812,7 +1853,9 @@ export class SqliteBackend implements Backend {
// Now delete!
- await (await this._prep(sqlObjectDataDeleteKey)).run({
+ await (
+ await this._prep(sqlObjectDataDeleteKey)
+ ).run({
object_store_id: scopeInfo.objectStoreId,
key: currKey,
});
@@ -1864,7 +1907,9 @@ export class SqliteBackend implements Backend {
);
}
const objectStoreId = await this._provideObjectStore(connInfo, scopeInfo);
- const metaRes = await (await
this._prep(sqlGetObjectStoreMetaById)).getFirst({
+ const metaRes = await (
+ await this._prep(sqlGetObjectStoreMetaById)
+ ).getFirst({
id: objectStoreId satisfies SqliteRowid,
});
if (metaRes === undefined) {
@@ -1928,14 +1973,18 @@ export class SqliteBackend implements Backend {
}
}
- await (await this._prep(sqlInsertObjectData)).run({
+ await (
+ await this._prep(sqlInsertObjectData)
+ ).run({
object_store_id: objectStoreId,
key: serializedObjectKey,
value: JSON.stringify(structuredEncapsulate(value)),
});
if (autoIncrement != 0) {
- await (await this._prep(sqlUpdateAutoIncrement)).run({
+ await (
+ await this._prep(sqlUpdateAutoIncrement)
+ ).run({
object_store_id: objectStoreId,
auto_increment: updatedKeyGenerator,
});
@@ -2053,7 +2102,9 @@ export class SqliteBackend implements Backend {
);
}
- await (await this._prep(sqlClearObjectStore)).run({
+ await (
+ await this._prep(sqlClearObjectStore)
+ ).run({
object_store_id: scopeInfo.objectStoreId,
});
diff --git a/packages/idb-bridge/src/bridge-idb.ts
b/packages/idb-bridge/src/bridge-idb.ts
index 6b710ea71..6552cee91 100644
--- a/packages/idb-bridge/src/bridge-idb.ts
+++ b/packages/idb-bridge/src/bridge-idb.ts
@@ -912,7 +912,9 @@ export class BridgeIDBFactory {
const requestedVersion = version;
if (BridgeIDBFactory.enableTracing) {
- console.log(`existing version of DB ${name} is ${existingVersion},
requesting ${requestedVersion}`);
+ console.log(
+ `existing version of DB ${name} is ${existingVersion}, requesting
${requestedVersion}`,
+ );
}
BridgeIDBFactory.enableTracing &&
@@ -2681,7 +2683,9 @@ export class BridgeIDBTransaction
);
if (!objectStoreMeta) {
- throw new NotFoundError();
+ throw new NotFoundError(
+ `object store metadata for ${name} found in current transaction
(bug!)`,
+ );
}
const newObjectStore = new BridgeIDBObjectStore(
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.