be even more safe in db

This commit is contained in:
Florian Dold 2016-10-18 01:36:47 +02:00
parent 89c3c2d58d
commit 700eb32f5a
2 changed files with 74 additions and 36 deletions

View File

@ -34,14 +34,23 @@ export class Store<T> {
} }
} }
export class Index<S,T> {
indexName: string;
storeName: string;
constructor(s: Store<T>, indexName: string) {
this.storeName = s.name;
this.indexName = indexName;
}
}
/** /**
* Stream that can be filtered, reduced or joined * Stream that can be filtered, reduced or joined
* with indices. * with indices.
*/ */
export interface QueryStream<T> { export interface QueryStream<T> {
indexJoin<S>(storeName: string, indexJoin<S,I>(index: Index<I,S>,
indexName: string, keyFn: (obj: T) => I): QueryStream<[T, S]>;
keyFn: (obj: any) => any): QueryStream<[T, S]>;
filter(f: (x: any) => boolean): QueryStream<T>; filter(f: (x: any) => boolean): QueryStream<T>;
reduce<S>(f: (v: T, acc: S) => S, start?: S): Promise<S>; reduce<S>(f: (v: T, acc: S) => S, start?: S): Promise<S>;
flatMap(f: (x: T) => T[]): QueryStream<T>; flatMap(f: (x: T) => T[]): QueryStream<T>;
@ -83,11 +92,10 @@ abstract class QueryStreamBase<T> implements QueryStream<T> {
return new QueryStreamFlatMap(this, f); return new QueryStreamFlatMap(this, f);
} }
indexJoin<S>(storeName: string, indexJoin<S,I>(index: Index<I,S>,
indexName: string, keyFn: (obj: T) => I): QueryStream<[T, S]> {
key: any): QueryStream<[T, S]> { this.root.addStoreAccess(index.storeName, false);
this.root.addStoreAccess(storeName, false); return new QueryStreamIndexJoin(this, index.storeName, index.indexName, keyFn);
return new QueryStreamIndexJoin(this, storeName, indexName, key);
} }
filter(f: (x: any) => boolean): QueryStream<T> { filter(f: (x: any) => boolean): QueryStream<T> {
@ -191,7 +199,8 @@ class QueryStreamIndexJoin<T, S> extends QueryStreamBase<[T, S]> {
key: any; key: any;
indexName: string; indexName: string;
constructor(s: QueryStreamBase<T>, storeName: string, indexName: string, key: any) { constructor(s: QueryStreamBase<T>, storeName: string, indexName: string,
key: any) {
super(s.root); super(s.root);
this.s = s; this.s = s;
this.storeName = storeName; this.storeName = storeName;
@ -287,10 +296,17 @@ export class QueryRoot {
this.db = db; this.db = db;
} }
iter<T>(store: Store<T>, iter<T>(store: Store<T>): QueryStream<T> {
{only = <string | undefined>undefined, indexName = <string | undefined>undefined} = {}): QueryStream<T> {
this.stores.add(store.name); this.stores.add(store.name);
return new IterQueryStream(this, store.name, { only, indexName }); return new IterQueryStream(this, store.name, {});
}
iterIndex<S,T>(index: Index<S,T>, only?: S): QueryStream<T> {
this.stores.add(index.storeName);
return new IterQueryStream(this, index.storeName, {
only,
indexName: index.indexName
});
} }
/** /**

View File

@ -30,7 +30,7 @@ import {
WireInfo, RefreshSession, ReserveRecord, CoinPaySig WireInfo, RefreshSession, ReserveRecord, CoinPaySig
} from "./types"; } from "./types";
import {HttpResponse, RequestException} from "./http"; import {HttpResponse, RequestException} from "./http";
import {QueryRoot, Store} from "./query"; import {QueryRoot, Store, Index} from "./query";
import {Checkable} from "./checkable"; import {Checkable} from "./checkable";
import {canonicalizeBaseUrl} from "./helpers"; import {canonicalizeBaseUrl} from "./helpers";
import {ReserveCreationInfo, Amounts} from "./types"; import {ReserveCreationInfo, Amounts} from "./types";
@ -306,12 +306,36 @@ function getWithdrawDenomList(amountAvailable: AmountJson,
namespace Stores { namespace Stores {
export let exchanges: Store<IExchangeInfo> = new Store<IExchangeInfo>("exchanges"); class ExchangeStore extends Store<IExchangeInfo> {
constructor() {
super("exchanges");
}
pubKeyIndex = new Index<string,IExchangeInfo>(this, "pubKey");
}
class CoinsStore extends Store<Coin> {
constructor() {
super("coins");
}
exchangeBaseUrlIndex = new Index<string,Coin>(this, "exchangeBaseUrl");
}
class HistoryStore extends Store<HistoryRecord> {
constructor() {
super("history");
}
timestampIndex = new Index<number,HistoryRecord>(this, "timestamp");
}
export let exchanges: ExchangeStore = new ExchangeStore();
export let transactions: Store<Transaction> = new Store<Transaction>("transactions"); export let transactions: Store<Transaction> = new Store<Transaction>("transactions");
export let reserves: Store<ReserveRecord> = new Store<ReserveRecord>("reserves"); export let reserves: Store<ReserveRecord> = new Store<ReserveRecord>("reserves");
export let coins: Store<Coin> = new Store<Coin>("coins"); export let coins: CoinsStore = new CoinsStore();
export let refresh: Store<RefreshSession> = new Store<RefreshSession>("refresh"); export let refresh: Store<RefreshSession> = new Store<RefreshSession>("refresh");
export let history: Store<HistoryRecord> = new Store<HistoryRecord>("history"); export let history: HistoryStore = new HistoryStore();
export let precoins: Store<PreCoin> = new Store<PreCoin>("precoins"); export let precoins: Store<PreCoin> = new Store<PreCoin>("precoins");
} }
@ -463,9 +487,8 @@ export class Wallet {
console.log("Checking for merchant's exchange", JSON.stringify(info)); console.log("Checking for merchant's exchange", JSON.stringify(info));
return [ return [
this.q() this.q()
.iter(Stores.exchanges, {indexName: "pubKey", only: info.master_pub}) .iterIndex(Stores.exchanges.pubKeyIndex, info.master_pub)
.indexJoin("coins", .indexJoin(Stores.coins.exchangeBaseUrlIndex,
"exchangeBaseUrl",
(exchange) => exchange.baseUrl) (exchange) => exchange.baseUrl)
.reduce((x) => storeExchangeCoin(x, info.url)) .reduce((x) => storeExchangeCoin(x, info.url))
]; ];
@ -997,8 +1020,7 @@ export class Wallet {
private async suspendCoins(exchangeInfo: IExchangeInfo): Promise<void> { private async suspendCoins(exchangeInfo: IExchangeInfo): Promise<void> {
let suspendedCoins = await ( let suspendedCoins = await (
this.q() this.q()
.iter(Stores.coins, .iterIndex(Stores.coins.exchangeBaseUrlIndex, exchangeInfo.baseUrl)
{indexName: "exchangeBaseUrl", only: exchangeInfo.baseUrl})
.reduce((coin: Coin, suspendedCoins: Coin[]) => { .reduce((coin: Coin, suspendedCoins: Coin[]) => {
if (!exchangeInfo.active_denoms.find((c) => c.denom_pub == coin.denomPub)) { if (!exchangeInfo.active_denoms.find((c) => c.denom_pub == coin.denomPub)) {
return Array.prototype.concat(suspendedCoins, [coin]); return Array.prototype.concat(suspendedCoins, [coin]);
@ -1375,7 +1397,7 @@ export class Wallet {
let history = await ( let history = await (
this.q() this.q()
.iter(Stores.history, {indexName: "timestamp"}) .iterIndex(Stores.history.timestampIndex)
.reduce(collect, [])); .reduce(collect, []));
return {history}; return {history};