forked from mystiq/hydrogen-web
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
|
// avoid corrupting state by only
|
||||||
// storing the sync up till the point
|
// storing the sync up till the point
|
||||||
// the exception occurred
|
// the exception occurred
|
||||||
try {
|
syncTxn.abort(log);
|
||||||
syncTxn.abort();
|
throw syncTxn.getCause(err);
|
||||||
} catch (abortErr) {
|
|
||||||
log.set("couldNotAbortTxn", true);
|
|
||||||
}
|
}
|
||||||
throw err;
|
await syncTxn.complete(log);
|
||||||
}
|
|
||||||
await syncTxn.complete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_afterSync(sessionState, inviteStates, roomStates, archivedRoomStates, log) {
|
_afterSync(sessionState, inviteStates, roomStates, archivedRoomStates, log) {
|
||||||
|
|
|
@ -159,13 +159,39 @@ export class Transaction {
|
||||||
return this._store(StoreNames.accountData, idbStore => new AccountDataStore(idbStore));
|
return this._store(StoreNames.accountData, idbStore => new AccountDataStore(idbStore));
|
||||||
}
|
}
|
||||||
|
|
||||||
complete(): Promise<void> {
|
async complete(log?: LogItem): Promise<void> {
|
||||||
return txnAsPromise(this._txn);
|
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?
|
// TODO: should we wrap the exception in a StorageError?
|
||||||
|
try {
|
||||||
this._txn.abort();
|
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) {
|
addWriteError(error: StorageError, refItem: LogItem | undefined, operationName: string, key: IDBValidKey | IDBKeyRange | undefined) {
|
||||||
// don't log subsequent `AbortError`s
|
// don't log subsequent `AbortError`s
|
||||||
if (error.errcode !== "AbortError" || this._writeErrors.length === 0) {
|
if (error.errcode !== "AbortError" || this._writeErrors.length === 0) {
|
||||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
|
|
||||||
import { IDBRequestError } from "./error";
|
import { IDBRequestError } from "./error";
|
||||||
import { StorageError } from "../common";
|
import { StorageError } from "../common";
|
||||||
|
import { AbortError } from "../../../utils/error.js";
|
||||||
|
|
||||||
let needsSyncPromise = false;
|
let needsSyncPromise = false;
|
||||||
|
|
||||||
|
@ -112,22 +113,8 @@ export function txnAsPromise(txn): Promise<void> {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
needsSyncPromise && Promise._flush && Promise._flush();
|
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 => {
|
txn.addEventListener("abort", event => {
|
||||||
if (!error) {
|
reject(new AbortError());
|
||||||
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);
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
needsSyncPromise && Promise._flush && Promise._flush();
|
needsSyncPromise && Promise._flush && Promise._flush();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue