process write errors on complete or abort in transaction
This commit is contained in:
parent
533b0f40d3
commit
ad45016b87
3 changed files with 35 additions and 26 deletions
|
@ -296,14 +296,10 @@ export class Sync {
|
|||
// avoid corrupting state by only
|
||||
// storing the sync up till the point
|
||||
// the exception occurred
|
||||
try {
|
||||
syncTxn.abort();
|
||||
} catch (abortErr) {
|
||||
log.set("couldNotAbortTxn", true);
|
||||
}
|
||||
throw err;
|
||||
syncTxn.abort(log);
|
||||
throw syncTxn.getCause(err);
|
||||
}
|
||||
await syncTxn.complete();
|
||||
await syncTxn.complete(log);
|
||||
}
|
||||
|
||||
_afterSync(sessionState, inviteStates, roomStates, archivedRoomStates, log) {
|
||||
|
|
|
@ -159,13 +159,39 @@ export class Transaction {
|
|||
return this._store(StoreNames.accountData, idbStore => new AccountDataStore(idbStore));
|
||||
}
|
||||
|
||||
complete(): Promise<void> {
|
||||
return txnAsPromise(this._txn);
|
||||
async complete(log?: LogItem): Promise<void> {
|
||||
try {
|
||||
await txnAsPromise(this._txn);
|
||||
} catch (err) {
|
||||
if (this._writeErrors.length) {
|
||||
this._logWriteErrors(log);
|
||||
throw this._writeErrors[0].error;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
abort(): void {
|
||||
getCause(error: Error) {
|
||||
if (error instanceof StorageError) {
|
||||
if (error.errcode === "AbortError" && this._writeErrors.length) {
|
||||
return this._writeErrors[0].error;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
abort(log?: LogItem): void {
|
||||
// TODO: should we wrap the exception in a StorageError?
|
||||
this._txn.abort();
|
||||
try {
|
||||
this._txn.abort();
|
||||
} catch (abortErr) {
|
||||
log?.set("couldNotAbortTxn", true);
|
||||
}
|
||||
if (this._writeErrors.length) {
|
||||
this._logWriteErrors(log);
|
||||
}
|
||||
}
|
||||
|
||||
addWriteError(error: StorageError, refItem: LogItem | undefined, operationName: string, key: IDBValidKey | IDBKeyRange | undefined) {
|
||||
// don't log subsequent `AbortError`s
|
||||
if (error.errcode !== "AbortError" || this._writeErrors.length === 0) {
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
|
||||
import { IDBRequestError } from "./error";
|
||||
import { StorageError } from "../common";
|
||||
import { AbortError } from "../../../utils/error.js";
|
||||
|
||||
let needsSyncPromise = false;
|
||||
|
||||
|
@ -112,22 +113,8 @@ export function txnAsPromise(txn): Promise<void> {
|
|||
// @ts-ignore
|
||||
needsSyncPromise && Promise._flush && Promise._flush();
|
||||
});
|
||||
txn.addEventListener("error", event => {
|
||||
const request = event.target;
|
||||
// catch first error here, but don't reject yet,
|
||||
// as we don't have access to the failed request in the abort event handler
|
||||
if (!error && request) {
|
||||
error = new IDBRequestError(request);
|
||||
}
|
||||
});
|
||||
txn.addEventListener("abort", event => {
|
||||
if (!error) {
|
||||
const txn = event.target;
|
||||
const dbName = txn.db.name;
|
||||
const storeNames = Array.from(txn.objectStoreNames).join(", ")
|
||||
error = new StorageError(`Transaction on ${dbName} with stores ${storeNames} was aborted.`);
|
||||
}
|
||||
reject(error);
|
||||
reject(new AbortError());
|
||||
// @ts-ignore
|
||||
needsSyncPromise && Promise._flush && Promise._flush();
|
||||
});
|
||||
|
|
Reference in a new issue