From 1963635dd72e9bf7a31662f1042848b3b04166e1 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 22 Sep 2021 10:22:52 +0200 Subject: [PATCH] also log index keys for a value when write fails in Store --- src/matrix/storage/idb/Store.ts | 45 +++++++++++++++++++++------ src/matrix/storage/idb/Transaction.ts | 10 +++--- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/matrix/storage/idb/Store.ts b/src/matrix/storage/idb/Store.ts index 83627047..e3d6e3f7 100644 --- a/src/matrix/storage/idb/Store.ts +++ b/src/matrix/storage/idb/Store.ts @@ -17,7 +17,7 @@ limitations under the License. import {QueryTarget, IDBQuery} from "./QueryTarget"; import {IDBRequestError, IDBRequestAttemptError} from "./error"; import {reqAsPromise} from "./utils"; -import {Transaction} from "./Transaction"; +import {Transaction, IDBKey} from "./Transaction"; import {LogItem} from "../../../logging/LogItem.js"; const LOG_REQUESTS = false; @@ -126,6 +126,10 @@ class QueryTargetWrapper { throw new IDBRequestAttemptError("index", this._qt, err, [name]); } } + + get indexNames(): string[] { + return Array.from(this._qtStore.indexNames); + } } export class Store extends QueryTarget { @@ -176,7 +180,7 @@ export class Store extends QueryTarget { return true; } catch (err) { if (err instanceof IDBRequestError) { - log.log({l: "could not write", id: this._getKey(value), e: err}, log.level.Warn); + log.log({l: "could not write", id: this._getKeys(value), e: err}, log.level.Warn); err.preventTransactionAbort(); return false; } else { @@ -191,24 +195,45 @@ export class Store extends QueryTarget { this._prepareErrorLog(request, log, "delete", keyOrKeyRange, undefined); } - private _prepareErrorLog(request: IDBRequest, log: LogItem | undefined, operationName: string, key: IDBValidKey | IDBKeyRange | undefined, value: T | undefined) { + private _prepareErrorLog(request: IDBRequest, log: LogItem | undefined, operationName: string, key: IDBKey | undefined, value: T | undefined) { if (log) { log.ensureRefId(); } reqAsPromise(request).catch(err => { + let keys : IDBKey[] | undefined = undefined; try { - if (!key && value) { - key = this._getKey(value); + if (value) { + keys = this._getKeys(value); + } else if (key) { + keys = [key]; } - } catch { - key = "getKey failed"; + } catch (err) { + console.error("_getKeys failed", err); } - this._transaction.addWriteError(err, log, operationName, key); + this._transaction.addWriteError(err, log, operationName, keys); }); } - private _getKey(value: T): IDBValidKey { + private _getKeys(value: T): IDBValidKey[] { + const keys: IDBValidKey[] = []; const {keyPath} = this._idbStore; + try { + keys.push(this._readKeyPath(value, keyPath)); + } catch (err) { + console.warn("could not read keyPath", keyPath); + } + for (const indexName of this._idbStore.indexNames) { + try { + const index = this._idbStore.index(indexName); + keys.push(this._readKeyPath(value, index.keyPath)); + } catch (err) { + console.warn("could not read index", indexName); + } + } + return keys; + } + + private _readKeyPath(value: T, keyPath: string[] | string): IDBValidKey { if (Array.isArray(keyPath)) { let field: any = value; for (const part of keyPath) { @@ -221,6 +246,6 @@ export class Store extends QueryTarget { return field as IDBValidKey; } else { return value[keyPath] as IDBValidKey; - } + } } } diff --git a/src/matrix/storage/idb/Transaction.ts b/src/matrix/storage/idb/Transaction.ts index 84247428..cd68457c 100644 --- a/src/matrix/storage/idb/Transaction.ts +++ b/src/matrix/storage/idb/Transaction.ts @@ -39,12 +39,14 @@ import {AccountDataStore} from "./stores/AccountDataStore"; import {LogItem} from "../../../logging/LogItem.js"; import {BaseLogger} from "../../../logging/BaseLogger.js"; +export type IDBKey = IDBValidKey | IDBKeyRange; + class WriteErrorInfo { constructor( public readonly error: StorageError, public readonly refItem: LogItem | undefined, public readonly operationName: string, - public readonly key: IDBValidKey | IDBKeyRange | undefined, + public readonly keys: IDBKey[] | undefined, ) {} } @@ -192,10 +194,10 @@ export class Transaction { } } - addWriteError(error: StorageError, refItem: LogItem | undefined, operationName: string, key: IDBValidKey | IDBKeyRange | undefined) { + addWriteError(error: StorageError, refItem: LogItem | undefined, operationName: string, keys: IDBKey[] | undefined) { // don't log subsequent `AbortError`s if (error.errcode !== "AbortError" || this._writeErrors.length === 0) { - this._writeErrors.push(new WriteErrorInfo(error, refItem, operationName, key)); + this._writeErrors.push(new WriteErrorInfo(error, refItem, operationName, keys)); } } @@ -206,7 +208,7 @@ export class Transaction { errorGroupItem.set("allowedStoreNames", this._allowedStoreNames); } for (const info of this._writeErrors) { - errorGroupItem.wrap({l: info.operationName, id: info.key}, item => { + errorGroupItem.wrap({l: info.operationName, id: info.keys}, item => { if (info.refItem) { item.refDetached(info.refItem); }