gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: wallet-core: fix exchange man


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: fix exchange management test case, surface exchange update error info in list
Date: Wed, 02 Nov 2022 14:23:28 +0100

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

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

The following commit(s) were added to refs/heads/master by this push:
     new 1e6e1a22c wallet-core: fix exchange management test case, surface 
exchange update error info in list
1e6e1a22c is described below

commit 1e6e1a22cdb16975f3a914b2f1be6db0ae1b241d
Author: Florian Dold <florian@dold.me>
AuthorDate: Wed Nov 2 14:23:26 2022 +0100

    wallet-core: fix exchange management test case, surface exchange update 
error info in list
---
 packages/taler-util/src/wallet-types.ts            | 10 +++++
 .../integrationtests/test-exchange-management.ts   | 14 +++++--
 .../taler-wallet-core/src/operations/common.ts     | 44 +++++++++++++++++-----
 .../taler-wallet-core/src/operations/exchanges.ts  | 13 +++++--
 .../taler-wallet-core/src/operations/recoup.ts     |  4 +-
 .../taler-wallet-core/src/operations/withdraw.ts   |  8 +++-
 packages/taler-wallet-core/src/util/retries.ts     |  5 ++-
 packages/taler-wallet-core/src/wallet.ts           |  8 +++-
 8 files changed, 84 insertions(+), 22 deletions(-)

diff --git a/packages/taler-util/src/wallet-types.ts 
b/packages/taler-util/src/wallet-types.ts
index 9d95f1ee2..5ff906faa 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -904,6 +904,10 @@ export enum ExchangeEntryStatus {
   Ok = "ok",
 }
 
+export interface OperationErrorInfo {
+  error: TalerErrorDetail;
+}
+
 // FIXME: This should probably include some error status.
 export interface ExchangeListItem {
   exchangeBaseUrl: string;
@@ -917,6 +921,12 @@ export interface ExchangeListItem {
    * temporarily queried.
    */
   permanent: boolean;
+
+  /**
+   * Information about the last error that occured when trying
+   * to update the exchange info.
+   */
+  lastUpdateErrorInfo?: OperationErrorInfo;
 }
 
 const codecForAuditorDenomSig = (): Codec<AuditorDenomSig> =>
diff --git 
a/packages/taler-wallet-cli/src/integrationtests/test-exchange-management.ts 
b/packages/taler-wallet-cli/src/integrationtests/test-exchange-management.ts
index f0b4ac8c9..6b63c3741 100644
--- a/packages/taler-wallet-cli/src/integrationtests/test-exchange-management.ts
+++ b/packages/taler-wallet-cli/src/integrationtests/test-exchange-management.ts
@@ -194,12 +194,16 @@ export async function runExchangeManagementTest(
   t.assertTrue(
     err1.errorDetail.code === 
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
   );
-
   exchangesList = await wallet.client.call(
     WalletApiOperation.ListExchanges,
     {},
   );
-  t.assertTrue(exchangesList.exchanges.length === 0);
+  console.log("exchanges list", j2s(exchangesList));
+  t.assertTrue(exchangesList.exchanges.length === 1);
+  t.assertTrue(
+    exchangesList.exchanges[0].lastUpdateErrorInfo?.error.code ===
+      TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
+  );
 
   /*
    * =========================================================================
@@ -240,7 +244,11 @@ export async function runExchangeManagementTest(
     WalletApiOperation.ListExchanges,
     {},
   );
-  t.assertTrue(exchangesList.exchanges.length === 0);
+  t.assertTrue(exchangesList.exchanges.length === 1);
+  t.assertTrue(
+    exchangesList.exchanges[0].lastUpdateErrorInfo?.error.code ===
+      TalerErrorCode.WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE,
+  );
 
   /*
    * =========================================================================
diff --git a/packages/taler-wallet-core/src/operations/common.ts 
b/packages/taler-wallet-core/src/operations/common.ts
index e29065390..f35556736 100644
--- a/packages/taler-wallet-core/src/operations/common.ts
+++ b/packages/taler-wallet-core/src/operations/common.ts
@@ -28,6 +28,7 @@ import {
   ExchangeTosStatus,
   j2s,
   Logger,
+  OperationErrorInfo,
   RefreshReason,
   TalerErrorCode,
   TalerErrorDetail,
@@ -224,30 +225,37 @@ export async function storeOperationPending(
     });
 }
 
-export async function runOperationWithErrorReporting(
+export async function runOperationWithErrorReporting<T1, T2>(
   ws: InternalWalletState,
   opId: string,
-  f: () => Promise<OperationAttemptResult>,
-): Promise<void> {
+  f: () => Promise<OperationAttemptResult<T1, T2>>,
+): Promise<OperationAttemptResult<T1, T2>> {
   let maybeError: TalerErrorDetail | undefined;
   try {
     const resp = await f();
     switch (resp.type) {
       case OperationAttemptResultType.Error:
-        return await storeOperationError(ws, opId, resp.errorDetail);
+        await storeOperationError(ws, opId, resp.errorDetail);
+        return resp;
       case OperationAttemptResultType.Finished:
-        return await storeOperationFinished(ws, opId);
+        await storeOperationFinished(ws, opId);
+        return resp;
       case OperationAttemptResultType.Pending:
-        return await storeOperationPending(ws, opId);
+        await storeOperationPending(ws, opId);
+        return resp;
       case OperationAttemptResultType.Longpoll:
-        break;
+        return resp;
     }
   } catch (e) {
     if (e instanceof TalerError) {
       logger.warn("operation processed resulted in error");
       logger.warn(`error was: ${j2s(e.errorDetail)}`);
       maybeError = e.errorDetail;
-      return await storeOperationError(ws, opId, maybeError!);
+      await storeOperationError(ws, opId, maybeError!);
+      return {
+        type: OperationAttemptResultType.Error,
+        errorDetail: e.errorDetail,
+      };
     } else if (e instanceof Error) {
       // This is a bug, as we expect pending operations to always
       // do their own error handling and only throw 
WALLET_PENDING_OPERATION_FAILED
@@ -261,7 +269,11 @@ export async function runOperationWithErrorReporting(
         },
         `unexpected exception (message: ${e.message})`,
       );
-      return await storeOperationError(ws, opId, maybeError);
+      await storeOperationError(ws, opId, maybeError);
+      return {
+        type: OperationAttemptResultType.Error,
+        errorDetail: maybeError,
+      };
     } else {
       logger.error("Uncaught exception, value is not even an error.");
       maybeError = makeErrorDetail(
@@ -269,7 +281,11 @@ export async function runOperationWithErrorReporting(
         {},
         `unexpected exception (not even an error)`,
       );
-      return await storeOperationError(ws, opId, maybeError);
+      await storeOperationError(ws, opId, maybeError);
+      return {
+        type: OperationAttemptResultType.Error,
+        errorDetail: maybeError,
+      };
     }
   }
 }
@@ -357,7 +373,13 @@ export function getExchangeTosStatus(
 export function makeExchangeListItem(
   r: ExchangeRecord,
   exchangeDetails: ExchangeDetailsRecord | undefined,
+  lastError: TalerErrorDetail | undefined,
 ): ExchangeListItem {
+  const lastUpdateErrorInfo: OperationErrorInfo | undefined = lastError
+    ? {
+        error: lastError,
+      }
+    : undefined;
   if (!exchangeDetails) {
     return {
       exchangeBaseUrl: r.baseUrl,
@@ -367,6 +389,7 @@ export function makeExchangeListItem(
       exchangeStatus: ExchangeEntryStatus.Unknown,
       permanent: r.permanent,
       ageRestrictionOptions: [],
+      lastUpdateErrorInfo,
     };
   }
   let exchangeStatus;
@@ -381,5 +404,6 @@ export function makeExchangeListItem(
     ageRestrictionOptions: exchangeDetails.ageMask
       ? AgeRestriction.getAgeGroupsFromMask(exchangeDetails.ageMask)
       : [],
+    lastUpdateErrorInfo,
   };
 }
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts 
b/packages/taler-wallet-core/src/operations/exchanges.ts
index 41e63b956..23ff1479e 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -73,9 +73,11 @@ import {
 import {
   OperationAttemptResult,
   OperationAttemptResultType,
-  runOperationHandlerForResult,
+  RetryTags,
+  unwrapOperationHandlerResultOrThrow,
 } from "../util/retries.js";
 import { WALLET_EXCHANGE_PROTOCOL_VERSION } from "../versions.js";
+import { runOperationWithErrorReporting } from "./common.js";
 import { isWithdrawableDenom } from "./withdraw.js";
 
 const logger = new Logger("exchanges.ts");
@@ -546,8 +548,13 @@ export async function updateExchangeFromUrl(
   exchange: ExchangeRecord;
   exchangeDetails: ExchangeDetailsRecord;
 }> {
-  return runOperationHandlerForResult(
-    await updateExchangeFromUrlHandler(ws, baseUrl, options),
+  const canonUrl = canonicalizeBaseUrl(baseUrl);
+  return unwrapOperationHandlerResultOrThrow(
+    await runOperationWithErrorReporting(
+      ws,
+      RetryTags.forExchangeUpdateFromUrl(canonUrl),
+      () => updateExchangeFromUrlHandler(ws, canonUrl, options),
+    ),
   );
 }
 
diff --git a/packages/taler-wallet-core/src/operations/recoup.ts 
b/packages/taler-wallet-core/src/operations/recoup.ts
index c2df6115b..e92c805bd 100644
--- a/packages/taler-wallet-core/src/operations/recoup.ts
+++ b/packages/taler-wallet-core/src/operations/recoup.ts
@@ -54,7 +54,7 @@ import { checkDbInvariant } from "../util/invariants.js";
 import { GetReadWriteAccess } from "../util/query.js";
 import {
   OperationAttemptResult,
-  runOperationHandlerForResult,
+  unwrapOperationHandlerResultOrThrow,
 } from "../util/retries.js";
 import { createRefreshGroup, processRefreshGroup } from "./refresh.js";
 import { internalCreateWithdrawalGroup } from "./withdraw.js";
@@ -307,7 +307,7 @@ export async function processRecoupGroup(
     forceNow?: boolean;
   } = {},
 ): Promise<void> {
-  await runOperationHandlerForResult(
+  await unwrapOperationHandlerResultOrThrow(
     await processRecoupGroupHandler(ws, recoupGroupId, options),
   );
   return;
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts 
b/packages/taler-wallet-core/src/operations/withdraw.ts
index 0e6bb8339..a9ecdf369 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -1385,6 +1385,7 @@ export async function getWithdrawalDetailsForUri(
       x.exchangeDetails,
       x.exchangeTos,
       x.denominations,
+      x.operationRetries,
     ])
     .runReadOnly(async (tx) => {
       const exchangeRecords = await tx.exchanges.iter().toArray();
@@ -1396,8 +1397,13 @@ export async function getWithdrawalDetailsForUri(
         const denominations = await tx.denominations.indexes.byExchangeBaseUrl
           .iter(r.baseUrl)
           .toArray();
+        const retryRecord = await tx.operationRetries.get(
+          RetryTags.forExchangeUpdate(r),
+        );
         if (exchangeDetails && denominations) {
-          exchanges.push(makeExchangeListItem(r, exchangeDetails));
+          exchanges.push(
+            makeExchangeListItem(r, exchangeDetails, retryRecord?.lastError),
+          );
         }
       }
     });
diff --git a/packages/taler-wallet-core/src/util/retries.ts 
b/packages/taler-wallet-core/src/util/retries.ts
index 5e1089dc5..8861d4d1e 100644
--- a/packages/taler-wallet-core/src/util/retries.ts
+++ b/packages/taler-wallet-core/src/util/retries.ts
@@ -176,6 +176,9 @@ export namespace RetryTags {
   export function forExchangeUpdate(exch: ExchangeRecord): string {
     return `${PendingTaskType.ExchangeUpdate}:${exch.baseUrl}`;
   }
+  export function forExchangeUpdateFromUrl(exchBaseUrl: string): string {
+    return `${PendingTaskType.ExchangeUpdate}:${exchBaseUrl}`;
+  }
   export function forExchangeCheckRefresh(exch: ExchangeRecord): string {
     return `${PendingTaskType.ExchangeCheckRefresh}:${exch.baseUrl}`;
   }
@@ -246,7 +249,7 @@ export async function scheduleRetry(
 /**
  * Run an operation handler, expect a success result and extract the success 
value.
  */
-export async function runOperationHandlerForResult<T>(
+export async function unwrapOperationHandlerResultOrThrow<T>(
   res: OperationAttemptResult<T>,
 ): Promise<T> {
   switch (res.type) {
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index dbab6607e..d7d8a206f 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -239,7 +239,7 @@ import {
   GetReadOnlyAccess,
   GetReadWriteAccess,
 } from "./util/query.js";
-import { OperationAttemptResult } from "./util/retries.js";
+import { OperationAttemptResult, RetryTags } from "./util/retries.js";
 import { TimerAPI, TimerGroup } from "./util/timer.js";
 import {
   WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
@@ -650,12 +650,16 @@ async function getExchanges(
       x.exchangeDetails,
       x.exchangeTos,
       x.denominations,
+      x.operationRetries,
     ])
     .runReadOnly(async (tx) => {
       const exchangeRecords = await tx.exchanges.iter().toArray();
       for (const r of exchangeRecords) {
         const exchangeDetails = await getExchangeDetails(tx, r.baseUrl);
-        exchanges.push(makeExchangeListItem(r, exchangeDetails));
+        const opRetryRecord = await tx.operationRetries.get(
+          RetryTags.forExchangeUpdate(r),
+        );
+        exchanges.push(makeExchangeListItem(r, exchangeDetails, 
opRetryRecord?.lastError));
       }
     });
   return { exchanges };

-- 
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]