summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/query.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/query.ts')
-rw-r--r--packages/taler-wallet-core/src/query.ts126
1 files changed, 101 insertions, 25 deletions
diff --git a/packages/taler-wallet-core/src/query.ts b/packages/taler-wallet-core/src/query.ts
index bdc8df0c7..0a321b835 100644
--- a/packages/taler-wallet-core/src/query.ts
+++ b/packages/taler-wallet-core/src/query.ts
@@ -15,8 +15,9 @@
*/
/**
- * Database query abstractions.
- * @module Query
+ * @fileoverview
+ * Query helpers for IndexedDB databases.
+ *
* @author Florian Dold
*/
@@ -563,6 +564,7 @@ function runTx<Arg, Res>(
tx: IDBTransaction,
arg: Arg,
f: (t: Arg, t2: IDBTransaction) => Promise<Res>,
+ triggerContext: InternalTriggerContext,
): Promise<Res> {
const stack = Error("Failed transaction was started here.");
return new Promise((resolve, reject) => {
@@ -583,6 +585,7 @@ function runTx<Arg, Res>(
logger.error(`${stack.stack}`);
reject(Error(msg));
}
+ triggerContext.handleAfterCommit();
resolve(funResult);
};
tx.onerror = () => {
@@ -627,6 +630,7 @@ function runTx<Arg, Res>(
function makeReadContext(
tx: IDBTransaction,
storePick: { [n: string]: StoreWithIndexes<any, any, any> },
+ triggerContext: InternalTriggerContext,
): any {
const ctx: { [s: string]: StoreReadOnlyAccessor<any, any> } = {};
for (const storeAlias in storePick) {
@@ -639,10 +643,12 @@ function makeReadContext(
const indexName = indexDescriptor.name;
indexes[indexAlias] = {
get(key) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx.objectStore(storeName).index(indexName).get(key);
return requestToPromise(req);
},
iter(query) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx
.objectStore(storeName)
.index(indexName)
@@ -650,6 +656,7 @@ function makeReadContext(
return new ResultStream<any>(req);
},
getAll(query, count) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx
.objectStore(storeName)
.index(indexName)
@@ -657,6 +664,7 @@ function makeReadContext(
return requestToPromise(req);
},
getAllKeys(query, count) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx
.objectStore(storeName)
.index(indexName)
@@ -664,6 +672,7 @@ function makeReadContext(
return requestToPromise(req);
},
count(query) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx.objectStore(storeName).index(indexName).count(query);
return requestToPromise(req);
},
@@ -672,14 +681,17 @@ function makeReadContext(
ctx[storeAlias] = {
indexes,
get(key) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx.objectStore(storeName).get(key);
return requestToPromise(req);
},
getAll(query, count) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx.objectStore(storeName).getAll(query, count);
return requestToPromise(req);
},
iter(query) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx.objectStore(storeName).openCursor(query);
return new ResultStream<any>(req);
},
@@ -691,6 +703,7 @@ function makeReadContext(
function makeWriteContext(
tx: IDBTransaction,
storePick: { [n: string]: StoreWithIndexes<any, any, any> },
+ triggerContext: InternalTriggerContext,
): any {
const ctx: { [s: string]: StoreReadWriteAccessor<any, any> } = {};
for (const storeAlias in storePick) {
@@ -703,10 +716,12 @@ function makeWriteContext(
const indexName = indexDescriptor.name;
indexes[indexAlias] = {
get(key) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx.objectStore(storeName).index(indexName).get(key);
return requestToPromise(req);
},
iter(query) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx
.objectStore(storeName)
.index(indexName)
@@ -714,6 +729,7 @@ function makeWriteContext(
return new ResultStream<any>(req);
},
getAll(query, count) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx
.objectStore(storeName)
.index(indexName)
@@ -721,6 +737,7 @@ function makeWriteContext(
return requestToPromise(req);
},
getAllKeys(query, count) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx
.objectStore(storeName)
.index(indexName)
@@ -728,6 +745,7 @@ function makeWriteContext(
return requestToPromise(req);
},
count(query) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx.objectStore(storeName).index(indexName).count(query);
return requestToPromise(req);
},
@@ -736,18 +754,23 @@ function makeWriteContext(
ctx[storeAlias] = {
indexes,
get(key) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx.objectStore(storeName).get(key);
return requestToPromise(req);
},
getAll(query, count) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx.objectStore(storeName).getAll(query, count);
return requestToPromise(req);
},
iter(query) {
+ triggerContext.storesAccessed.add(storeName);
const req = tx.objectStore(storeName).openCursor(query);
return new ResultStream<any>(req);
},
async add(r, k) {
+ triggerContext.storesAccessed.add(storeName);
+ triggerContext.storesModified.add(storeName);
const req = tx.objectStore(storeName).add(r, k);
const key = await requestToPromise(req);
return {
@@ -755,6 +778,8 @@ function makeWriteContext(
};
},
async put(r, k) {
+ triggerContext.storesAccessed.add(storeName);
+ triggerContext.storesModified.add(storeName);
const req = tx.objectStore(storeName).put(r, k);
const key = await requestToPromise(req);
return {
@@ -762,6 +787,8 @@ function makeWriteContext(
};
},
delete(k) {
+ triggerContext.storesAccessed.add(storeName);
+ triggerContext.storesModified.add(storeName);
const req = tx.objectStore(storeName).delete(k);
return requestToPromise(req);
},
@@ -802,11 +829,47 @@ export interface DbAccess<StoreMap> {
): Promise<T>;
}
+export interface AfterCommitInfo {
+ mode: IDBTransactionMode;
+ scope: Set<string>;
+ accessedStores: Set<string>;
+ modifiedStores: Set<string>;
+}
+
export interface TriggerSpec {
/**
* Trigger run after every successful commit, run outside of the transaction.
*/
- afterCommit?: (mode: IDBTransactionMode, stores: string[]) => void;
+ afterCommit?: (info: AfterCommitInfo) => void;
+
+ // onRead(store, value)
+ // initState<State> () => State
+ // beforeCommit<State>? (tx: Transaction, s: State | undefined) => Promise<void>;
+}
+
+class InternalTriggerContext {
+ storesScope: Set<string>;
+ storesAccessed: Set<string> = new Set();
+ storesModified: Set<string> = new Set();
+
+ constructor(
+ private triggerSpec: TriggerSpec,
+ private mode: IDBTransactionMode,
+ scope: string[],
+ ) {
+ this.storesScope = new Set(scope);
+ }
+
+ handleAfterCommit() {
+ if (this.triggerSpec.afterCommit) {
+ this.triggerSpec.afterCommit({
+ mode: this.mode,
+ accessedStores: this.storesAccessed,
+ modifiedStores: this.storesModified,
+ scope: this.storesScope,
+ });
+ }
+ }
}
/**
@@ -842,12 +905,18 @@ export class DbAccessImpl<StoreMap> implements DbAccess<StoreMap> {
strStoreNames.push(swi.storeName);
accessibleStores[swi.storeName] = swi;
}
- const tx = this.db.transaction(strStoreNames, "readwrite");
- const writeContext = makeWriteContext(tx, accessibleStores);
- return runTx(tx, writeContext, txf);
+ const mode = "readwrite";
+ const triggerContext = new InternalTriggerContext(
+ this.triggers,
+ mode,
+ strStoreNames,
+ );
+ const tx = this.db.transaction(strStoreNames, mode);
+ const writeContext = makeWriteContext(tx, accessibleStores, triggerContext);
+ return runTx(tx, writeContext, txf, triggerContext);
}
- runAllStoresReadOnlyTx<T>(
+ async runAllStoresReadOnlyTx<T>(
options: {
label?: string;
},
@@ -863,12 +932,19 @@ export class DbAccessImpl<StoreMap> implements DbAccess<StoreMap> {
strStoreNames.push(swi.storeName);
accessibleStores[swi.storeName] = swi;
}
- const tx = this.db.transaction(strStoreNames, "readonly");
- const writeContext = makeReadContext(tx, accessibleStores);
- return runTx(tx, writeContext, txf);
+ const mode = "readonly";
+ const triggerContext = new InternalTriggerContext(
+ this.triggers,
+ mode,
+ strStoreNames,
+ );
+ const tx = this.db.transaction(strStoreNames, mode);
+ const writeContext = makeReadContext(tx, accessibleStores, triggerContext);
+ const res = await runTx(tx, writeContext, txf, triggerContext);
+ return res;
}
- runReadWriteTx<T, StoreNameArray extends Array<StoreNames<StoreMap>>>(
+ async runReadWriteTx<T, StoreNameArray extends Array<StoreNames<StoreMap>>>(
storeNames: StoreNameArray,
txf: (tx: DbReadWriteTransaction<StoreMap, StoreNameArray>) => Promise<T>,
): Promise<T> {
@@ -881,12 +957,14 @@ export class DbAccessImpl<StoreMap> implements DbAccess<StoreMap> {
accessibleStores[swi.storeName] = swi;
}
const mode = "readwrite";
+ const triggerContext = new InternalTriggerContext(
+ this.triggers,
+ mode,
+ strStoreNames,
+ );
const tx = this.db.transaction(strStoreNames, mode);
- const writeContext = makeWriteContext(tx, accessibleStores);
- const res = runTx(tx, writeContext, txf);
- if (this.triggers.afterCommit) {
- this.triggers.afterCommit(mode, strStoreNames);
- }
+ const writeContext = makeWriteContext(tx, accessibleStores, triggerContext);
+ const res = await runTx(tx, writeContext, txf, triggerContext);
return res;
}
@@ -903,16 +981,14 @@ export class DbAccessImpl<StoreMap> implements DbAccess<StoreMap> {
accessibleStores[swi.storeName] = swi;
}
const mode = "readonly";
+ const triggerContext = new InternalTriggerContext(
+ this.triggers,
+ mode,
+ strStoreNames,
+ );
const tx = this.db.transaction(strStoreNames, mode);
- const readContext = makeReadContext(tx, accessibleStores);
- const res = runTx(tx, readContext, txf);
- if (this.triggers.afterCommit) {
- this.triggers.afterCommit(mode, strStoreNames);
- }
+ const readContext = makeReadContext(tx, accessibleStores, triggerContext);
+ const res = runTx(tx, readContext, txf, triggerContext);
return res;
}
-
- registerPostCommitTrigger(args: {
- handler: (storeNames: string[]) => void;
- }): void {}
}