add Store.tryAdd, which prevent abort on ConstraintError

This commit is contained in:
Bruno Windels 2021-09-21 21:02:39 +02:00
parent 0d486a14f6
commit 12add19c31
3 changed files with 27 additions and 6 deletions

View file

@ -15,7 +15,7 @@ limitations under the License.
*/
import {QueryTarget, IDBQuery} from "./QueryTarget";
import {IDBRequestAttemptError} from "./error";
import {IDBRequestError, IDBRequestAttemptError} from "./error";
import {reqAsPromise} from "./utils";
import {Transaction} from "./Transaction";
import {LogItem} from "../../../logging/LogItem.js";
@ -170,6 +170,19 @@ export class Store<T> extends QueryTarget<T> {
this._prepareErrorLog(request, log, "add", undefined, value);
}
async tryAdd(value: T, log: LogItem): Promise<boolean> {
try {
await reqAsPromise(this._idbStore.add(value));
return true;
} catch (err) {
if (err instanceof IDBRequestError) {
log.log({l: "could not write", id: this._getKey(value), e: err}, log.level.Warn);
err.preventTransactionAbort();
}
return false;
}
}
delete(keyOrKeyRange: IDBValidKey | IDBKeyRange, log?: LogItem): void {
// ok to not monitor result of request, see comment in `put`.
const request = this._idbStore.delete(keyOrKeyRange);

View file

@ -57,10 +57,18 @@ export class IDBError extends StorageError {
}
export class IDBRequestError extends IDBError {
constructor(request: IDBRequest, message: string = "IDBRequest failed") {
private errorEvent: Event;
constructor(errorEvent: Event) {
const request = errorEvent.target as IDBRequest;
const source = request.source;
const cause = request.error;
super(message, source, cause);
super("IDBRequest failed", source, cause);
this.errorEvent = errorEvent;
}
preventTransactionAbort() {
this.errorEvent.preventDefault();
}
}

View file

@ -97,7 +97,7 @@ export function reqAsPromise<T>(req: IDBRequest<T>): Promise<T> {
needsSyncPromise && Promise._flush && Promise._flush();
});
req.addEventListener("error", event => {
const error = new IDBRequestError(event.target as IDBRequest<T>);
const error = new IDBRequestError(event);
reject(error);
// @ts-ignore
needsSyncPromise && Promise._flush && Promise._flush();
@ -143,8 +143,8 @@ type CursorIterator<T, I extends IDBCursor> = (value: I extends IDBCursorWithVal
export function iterateCursor<T, I extends IDBCursor = IDBCursorWithValue>(cursorRequest: IDBRequest<I | null>, processValue: CursorIterator<T, I>): Promise<boolean> {
// TODO: does cursor already have a value here??
return new Promise<boolean>((resolve, reject) => {
cursorRequest.onerror = () => {
reject(new IDBRequestError(cursorRequest));
cursorRequest.onerror = event => {
reject(new IDBRequestError(event));
// @ts-ignore
needsSyncPromise && Promise._flush && Promise._flush();
};