From b0b737f72ecc3cb96acff510906db9f818eab463 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 19 Oct 2016 18:40:29 +0200 Subject: show pending incoming amount --- lib/wallet/query.ts | 97 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 7 deletions(-) (limited to 'lib/wallet/query.ts') diff --git a/lib/wallet/query.ts b/lib/wallet/query.ts index 6255ffb94..3571c32c7 100644 --- a/lib/wallet/query.ts +++ b/lib/wallet/query.ts @@ -24,12 +24,19 @@ "use strict"; +export interface JoinResult { + left: L; + right: R; +} + + export class Store { name: string; validator?: (v: T) => T; storeParams: IDBObjectStoreParameters; - constructor(name: string, storeParams: IDBObjectStoreParameters, validator?: (v: T) => T) { + constructor(name: string, storeParams: IDBObjectStoreParameters, + validator?: (v: T) => T) { this.name = name; this.validator = validator; this.storeParams = storeParams; @@ -53,13 +60,16 @@ export class Index { */ export interface QueryStream { indexJoin(index: Index, - keyFn: (obj: T) => I): QueryStream<[T, S]>; - filter(f: (x: any) => boolean): QueryStream; + keyFn: (obj: T) => I): QueryStream<[T, S]>; + keyJoin(store: Store, + keyFn: (obj: T) => I): QueryStream>; + filter(f: (T: any) => boolean): QueryStream; reduce(f: (v: T, acc: S) => S, start?: S): Promise; flatMap(f: (x: T) => T[]): QueryStream; toArray(): Promise; } +export let AbortTransaction = Symbol("abort_transaction"); /** * Get an unresolved promise together with its extracted resolve / reject @@ -96,11 +106,17 @@ abstract class QueryStreamBase implements QueryStream { } indexJoin(index: Index, - keyFn: (obj: T) => I): QueryStream<[T, S]> { + keyFn: (obj: T) => I): QueryStream<[T, S]> { this.root.addStoreAccess(index.storeName, false); return new QueryStreamIndexJoin(this, index.storeName, index.indexName, keyFn); } + keyJoin(store: Store, + keyFn: (obj: T) => I): QueryStream> { + this.root.addStoreAccess(store.name, false); + return new QueryStreamKeyJoin(this, store.name, keyFn); + } + filter(f: (x: any) => boolean): QueryStream { return new QueryStreamFilter(this, f); } @@ -234,6 +250,42 @@ class QueryStreamIndexJoin extends QueryStreamBase<[T, S]> { } +class QueryStreamKeyJoin extends QueryStreamBase> { + s: QueryStreamBase; + storeName: string; + key: any; + + constructor(s: QueryStreamBase, storeName: string, + key: any) { + super(s.root); + this.s = s; + this.storeName = storeName; + this.key = key; + } + + subscribe(f: SubscribeFn) { + this.s.subscribe((isDone, value, tx) => { + if (isDone) { + f(true, undefined, tx); + return; + } + console.log("joining on", this.key(value)); + let s = tx.objectStore(this.storeName); + let req = s.openCursor(IDBKeyRange.only(this.key(value))); + req.onsuccess = () => { + let cursor = req.result; + if (cursor) { + f(false, {left:value, right: cursor.value}, tx); + cursor.continue(); + } else { + f(true, undefined, tx); + } + } + }); + } +} + + class IterQueryStream extends QueryStreamBase { private storeName: string; private options: any; @@ -304,7 +356,8 @@ export class QueryRoot { return new IterQueryStream(this, store.name, {}); } - iterIndex(index: Index, only?: S): QueryStream { + iterIndex(index: Index, + only?: S): QueryStream { this.stores.add(index.storeName); return new IterQueryStream(this, index.storeName, { only, @@ -326,6 +379,30 @@ export class QueryRoot { } + mutate(store: Store, key: any, f: (v: T) => T): QueryRoot { + let doPut = (tx: IDBTransaction) => { + let reqGet = tx.objectStore(store.name).get(key); + reqGet.onsuccess = () => { + let r = reqGet.result; + let m: T; + try { + m = f(r); + } catch (e) { + if (e == AbortTransaction) { + tx.abort(); + return; + } + throw e; + } + + tx.objectStore(store.name).put(m); + } + }; + this.addWork(doPut, store.name, true); + return this; + } + + /** * Add all object from an iterable to the given object store. * Fails if the object's key is already present @@ -380,7 +457,8 @@ export class QueryRoot { /** * Get one object from a store by its key. */ - getIndexed(index: Index, key: I): Promise { + getIndexed(index: Index, + key: I): Promise { if (key === void 0) { throw Error("key must not be undefined"); } @@ -388,7 +466,9 @@ export class QueryRoot { const {resolve, promise} = openPromise(); const doGetIndexed = (tx: IDBTransaction) => { - const req = tx.objectStore(index.storeName).index(index.indexName).get(key); + const req = tx.objectStore(index.storeName) + .index(index.indexName) + .get(key); req.onsuccess = () => { resolve(req.result); }; @@ -417,6 +497,9 @@ export class QueryRoot { tx.oncomplete = () => { resolve(); }; + tx.onabort = () => { + reject(Error("transaction aborted")); + }; for (let w of this.work) { w(tx); } -- cgit v1.2.3