gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] 01/03: fix tip record creation, migrate DB


From: gnunet
Subject: [taler-wallet-core] 01/03: fix tip record creation, migrate DB
Date: Mon, 16 Nov 2020 14:48:47 +0100

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

commit 292160f7e979a0d9fdea7430f0d26b2dc1122a16
Author: Florian Dold <florian@dold.me>
AuthorDate: Mon Nov 16 14:12:37 2020 +0100

    fix tip record creation, migrate DB
---
 packages/taler-wallet-core/src/db.ts             | 56 +++++++++++++++++-------
 packages/taler-wallet-core/src/operations/tip.ts |  6 ++-
 packages/taler-wallet-core/src/types/dbTypes.ts  | 13 ++++--
 packages/taler-wallet-core/src/util/helpers.ts   |  4 ++
 packages/taler-wallet-core/src/util/query.ts     | 28 ++++++++++--
 packages/taler-wallet-core/src/util/taleruri.ts  |  9 ++--
 pnpm-lock.yaml                                   |  2 +-
 7 files changed, 89 insertions(+), 29 deletions(-)

diff --git a/packages/taler-wallet-core/src/db.ts 
b/packages/taler-wallet-core/src/db.ts
index b94fd154..ac3c79e2 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -1,6 +1,7 @@
 import { Stores } from "./types/dbTypes";
 import { openDatabase, Database, Store, Index } from "./util/query";
-import { IDBFactory, IDBDatabase } from "idb-bridge";
+import { IDBFactory, IDBDatabase, IDBObjectStore, IDBTransaction } from 
"idb-bridge";
+import { Logger } from './util/logging';
 
 /**
  * Name of the Taler database.  This is effectively the major
@@ -17,7 +18,9 @@ const TALER_DB_NAME = "taler-wallet-prod-v1";
  * backwards-compatible way or object stores and indices
  * are added.
  */
-export const WALLET_DB_MINOR_VERSION = 1;
+export const WALLET_DB_MINOR_VERSION = 2;
+
+const logger = new Logger("db.ts");
 
 /**
  * Return a promise that resolves
@@ -31,24 +34,45 @@ export function openTalerDatabase(
     db: IDBDatabase,
     oldVersion: number,
     newVersion: number,
+    upgradeTransaction: IDBTransaction,
   ): void => {
-    switch (oldVersion) {
-      case 0: // DB does not exist yet
-        for (const n in Stores) {
-          if ((Stores as any)[n] instanceof Store) {
-            const si: Store<any> = (Stores as any)[n];
-            const s = db.createObjectStore(si.name, si.storeParams);
-            for (const indexName in si as any) {
-              if ((si as any)[indexName] instanceof Index) {
-                const ii: Index<any, any> = (si as any)[indexName];
-                s.createIndex(ii.indexName, ii.keyPath, ii.options);
-              }
+    if (oldVersion === 0) {
+      for (const n in Stores) {
+        if ((Stores as any)[n] instanceof Store) {
+          const si: Store<any> = (Stores as any)[n];
+          const s = db.createObjectStore(si.name, si.storeParams);
+          for (const indexName in si as any) {
+            if ((si as any)[indexName] instanceof Index) {
+              const ii: Index<any, any> = (si as any)[indexName];
+              s.createIndex(ii.indexName, ii.keyPath, ii.options);
+            }
+          }
+        }
+      }
+      return;
+    }
+    if (oldVersion === newVersion) {
+      return;
+    }
+    logger.info(`upgrading database from ${oldVersion} to ${newVersion}`);
+    for (const n in Stores) {
+      if ((Stores as any)[n] instanceof Store) {
+        const si: Store<any> = (Stores as any)[n];
+        let s: IDBObjectStore;
+        if ((si.storeParams?.versionAdded ?? 1) > oldVersion) {
+          s = db.createObjectStore(si.name, si.storeParams);
+        } else {
+          s = upgradeTransaction.objectStore(si.name);
+        }
+        for (const indexName in si as any) {
+          if ((si as any)[indexName] instanceof Index) {
+            const ii: Index<any, any> = (si as any)[indexName];
+            if ((ii.options?.versionAdded ?? 0) > oldVersion) {
+              s.createIndex(ii.indexName, ii.keyPath, ii.options);
             }
           }
         }
-        break;
-      default:
-        throw Error("unsupported existig DB version");
+      }
     }
   };
 
diff --git a/packages/taler-wallet-core/src/operations/tip.ts 
b/packages/taler-wallet-core/src/operations/tip.ts
index 08f45eb8..3b8ac026 100644
--- a/packages/taler-wallet-core/src/operations/tip.ts
+++ b/packages/taler-wallet-core/src/operations/tip.ts
@@ -46,6 +46,7 @@ import { Logger } from "../util/logging";
 import { checkDbInvariant } from "../util/invariants";
 import { TalerErrorCode } from "../TalerErrorCode";
 import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries";
+import { j2s } from '../util/helpers';
 
 const logger = new Logger("operations/tip.ts");
 
@@ -68,7 +69,7 @@ export async function prepareTip(
     merchantResp,
     codecForTipPickupGetResponse(),
   );
-  logger.trace(`status ${tipPickupStatus}`);
+  logger.trace(`status ${j2s(tipPickupStatus)}`);
 
   const amount = Amounts.parseOrThrow(tipPickupStatus.tip_amount);
 
@@ -80,6 +81,7 @@ export async function prepareTip(
   ]);
 
   if (!tipRecord) {
+    logger.trace("new tip, creating tip record");
     await updateExchangeFromUrl(ws, tipPickupStatus.exchange_url);
     const withdrawDetails = await getExchangeWithdrawalInfo(
       ws,
@@ -232,7 +234,7 @@ async function processTipImpl(
   }));
 
   const tipStatusUrl = new URL(
-    `/tips/${tipRecord.merchantTipId}/pickup`,
+    `tips/${tipRecord.merchantTipId}/pickup`,
     tipRecord.merchantBaseUrl,
   );
 
diff --git a/packages/taler-wallet-core/src/types/dbTypes.ts 
b/packages/taler-wallet-core/src/types/dbTypes.ts
index 8f6c22f2..ed3a18ae 100644
--- a/packages/taler-wallet-core/src/types/dbTypes.ts
+++ b/packages/taler-wallet-core/src/types/dbTypes.ts
@@ -361,7 +361,6 @@ export enum DenominationStatus {
   VerifiedBad,
 }
 
-
 /**
  * Denomination record as stored in the wallet's database.
  */
@@ -640,7 +639,7 @@ export interface PlanchetRecord {
   /**
    * Public key of the reserve that this planchet
    * is being withdrawn from.
-   * 
+   *
    * Can be the empty string (non-null/undefined for DB indexing)
    * if this is a tipping reserve.
    */
@@ -1532,7 +1531,6 @@ export enum ImportPayloadType {
   CoreSchema = "core-schema",
 }
 
-
 class ExchangesStore extends Store<ExchangeRecord> {
   constructor() {
     super("exchanges", { keyPath: "baseUrl" });
@@ -1624,6 +1622,15 @@ class TipsStore extends Store<TipRecord> {
   constructor() {
     super("tips", { keyPath: "walletTipId" });
   }
+  // Added in version 2
+  byMerchantTipIdAndBaseUrl = new Index<[string, string], TipRecord>(
+    this,
+    "tipsByMerchantTipIdAndOriginIndex",
+    ["merchantTipId", "merchantBaseUrl"],
+    {
+      versionAdded: 2,
+    }
+  );
 }
 
 class WithdrawalGroupsStore extends Store<WithdrawalGroupRecord> {
diff --git a/packages/taler-wallet-core/src/util/helpers.ts 
b/packages/taler-wallet-core/src/util/helpers.ts
index ae4b0359..570df441 100644
--- a/packages/taler-wallet-core/src/util/helpers.ts
+++ b/packages/taler-wallet-core/src/util/helpers.ts
@@ -146,3 +146,7 @@ export function strcmp(s1: string, s2: string): number {
   }
   return 0;
 }
+
+export function j2s(x: any): string {
+  return JSON.stringify(x, undefined, 2);
+}
\ No newline at end of file
diff --git a/packages/taler-wallet-core/src/util/query.ts 
b/packages/taler-wallet-core/src/util/query.ts
index 6ebc3bbc..f533c4cf 100644
--- a/packages/taler-wallet-core/src/util/query.ts
+++ b/packages/taler-wallet-core/src/util/query.ts
@@ -44,14 +44,25 @@ const logger = new Logger("query.ts");
  */
 export const TransactionAbort = Symbol("transaction_abort");
 
+export interface StoreParams<T> {
+  validator?: (v: T) => T;
+  autoIncrement?: boolean;
+  keyPath?: string | string[] | null;
+
+  /**
+   * Database version that this store was added in, or
+   * undefined if added in the first version.
+   */
+  versionAdded?: number;
+}
+
 /**
  * Definition of an object store.
  */
 export class Store<T> {
   constructor(
     public name: string,
-    public storeParams?: IDBObjectStoreParameters,
-    public validator?: (v: T) => T,
+    public storeParams?: StoreParams<T>,
   ) {}
 }
 
@@ -66,6 +77,12 @@ export interface IndexOptions {
    * Defaults to false.
    */
   multiEntry?: boolean;
+
+  /**
+   * Database version that this store was added in, or
+   * undefined if added in the first version.
+   */
+  versionAdded?: number;
 }
 
 function requestToPromise(req: IDBRequest): Promise<any> {
@@ -425,6 +442,7 @@ export function openDatabase(
     db: IDBDatabase,
     oldVersion: number,
     newVersion: number,
+    upgradeTransaction: IDBTransaction,
   ) => void,
 ): Promise<IDBDatabase> {
   return new Promise<IDBDatabase>((resolve, reject) => {
@@ -449,7 +467,11 @@ export function openDatabase(
       if (!newVersion) {
         throw Error("upgrade needed, but new version unknown");
       }
-      onUpgradeNeeded(db, e.oldVersion, newVersion);
+      const transaction = req.transaction;
+      if (!transaction) {
+        throw Error("no transaction handle available in upgrade handler");
+      }
+      onUpgradeNeeded(db, e.oldVersion, newVersion, transaction);
     };
   });
 }
diff --git a/packages/taler-wallet-core/src/util/taleruri.ts 
b/packages/taler-wallet-core/src/util/taleruri.ts
index 839d0b29..ee055a32 100644
--- a/packages/taler-wallet-core/src/util/taleruri.ts
+++ b/packages/taler-wallet-core/src/util/taleruri.ts
@@ -14,6 +14,7 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
+import { canonicalizeBaseUrl } from './helpers';
 import { URLSearchParams } from "./url";
 
 export interface PayUriResult {
@@ -59,7 +60,7 @@ export function parseWithdrawUri(s: string): 
WithdrawUriResult | undefined {
   const p = [host, ...pathSegments].join("/");
 
   return {
-    bankIntegrationApiBaseUrl: `${pi.innerProto}://${p}/`,
+    bankIntegrationApiBaseUrl: canonicalizeBaseUrl(`${pi.innerProto}://${p}/`),
     withdrawalOperationId: withdrawId,
   };
 }
@@ -155,7 +156,7 @@ export function parsePayUri(s: string): PayUriResult | 
undefined {
   const orderId = parts[parts.length - 2];
   const pathSegments = parts.slice(1, parts.length - 2);
   const p = [host, ...pathSegments].join("/");
-  const merchantBaseUrl = `${pi.innerProto}://${p}/`;
+  const merchantBaseUrl = canonicalizeBaseUrl(`${pi.innerProto}://${p}/`);
 
   return {
     merchantBaseUrl,
@@ -183,7 +184,7 @@ export function parseTipUri(s: string): TipUriResult | 
undefined {
   const tipId = parts[parts.length - 1];
   const pathSegments = parts.slice(1, parts.length - 1);
   const p = [host, ...pathSegments].join("/");
-  const merchantBaseUrl = `${pi.innerProto}://${p}/`;
+  const merchantBaseUrl = canonicalizeBaseUrl(`${pi.innerProto}://${p}/`);
 
   return {
     merchantBaseUrl,
@@ -210,7 +211,7 @@ export function parseRefundUri(s: string): RefundUriResult 
| undefined {
   const orderId = parts[parts.length - 2];
   const pathSegments = parts.slice(1, parts.length - 2);
   const p = [host, ...pathSegments].join("/");
-  const merchantBaseUrl = `${pi.innerProto}://${p}/`;
+  const merchantBaseUrl = canonicalizeBaseUrl(`${pi.innerProto}://${p}/`);
 
   return {
     merchantBaseUrl,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f8b23685..5bca329c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -233,7 +233,7 @@ importers:
       taler-wallet-core: 'workspace:*'
       tslib: ^2.0.1
       typescript: ^3.9.7
-lockfileVersion: 5.1
+lockfileVersion: 5.2
 packages:
   /@ava/typescript/1.1.1:
     dependencies:

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]