gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated (490ef893e -> b70f922fd)


From: gnunet
Subject: [taler-wallet-core] branch master updated (490ef893e -> b70f922fd)
Date: Fri, 16 Feb 2024 13:39:18 +0100

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

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

    from 490ef893e taler-util: cancellation and timeouts on NodeJS
     new c909d6fc0 taler-util: cancellation and timeouts on qjs
     new b70f922fd wallet-core: make templateParams optional

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 packages/taler-harness/src/harness/harness.ts      |   2 +-
 packages/taler-util/src/http-impl.qtart.ts         |  80 ++++++++++++++-
 packages/taler-util/src/index.ts                   |   1 +
 packages/taler-util/src/wallet-types.ts            |   2 +-
 .../src/crypto/workers/crypto-dispatcher.ts        |  12 ++-
 packages/taler-wallet-core/src/index.ts            |   1 -
 .../taler-wallet-core/src/internal-wallet-state.ts |   1 -
 .../taler-wallet-core/src/operations/exchanges.ts  |   2 +-
 .../src/operations/pay-merchant.ts                 |  28 +++---
 .../taler-wallet-core/src/operations/testing.ts    |   8 +-
 packages/taler-wallet-core/src/remote.ts           |   3 +-
 packages/taler-wallet-core/src/shepherd.ts         |   2 +-
 .../taler-wallet-core/src/util/promiseUtils.ts     | 112 ---------------------
 packages/taler-wallet-core/src/util/query.ts       |   3 +-
 packages/taler-wallet-core/src/wallet.ts           |   8 +-
 packages/taler-wallet-embedded/src/wallet-qjs.ts   |   3 +-
 16 files changed, 116 insertions(+), 152 deletions(-)
 delete mode 100644 packages/taler-wallet-core/src/util/promiseUtils.ts

diff --git a/packages/taler-harness/src/harness/harness.ts 
b/packages/taler-harness/src/harness/harness.ts
index 975d73cf8..410462af2 100644
--- a/packages/taler-harness/src/harness/harness.ts
+++ b/packages/taler-harness/src/harness/harness.ts
@@ -44,6 +44,7 @@ import {
   encodeCrock,
   hash,
   j2s,
+  openPromise,
   parsePaytoUri,
   stringToBytes,
 } from "@gnu-taler/taler-util";
@@ -57,7 +58,6 @@ import {
   WalletCoreRequestType,
   WalletCoreResponseType,
   WalletOperations,
-  openPromise,
 } from "@gnu-taler/taler-wallet-core";
 import {
   RemoteWallet,
diff --git a/packages/taler-util/src/http-impl.qtart.ts 
b/packages/taler-util/src/http-impl.qtart.ts
index a37029d6e..0be9f2c23 100644
--- a/packages/taler-util/src/http-impl.qtart.ts
+++ b/packages/taler-util/src/http-impl.qtart.ts
@@ -19,9 +19,9 @@
 /**
  * Imports.
  */
-import { Logger } from "@gnu-taler/taler-util";
+import { Logger, openPromise } from "@gnu-taler/taler-util";
 import { TalerError } from "./errors.js";
-import { encodeBody, getDefaultHeaders, HttpLibArgs } from "./http-common.js";
+import { HttpLibArgs, encodeBody, getDefaultHeaders } from "./http-common.js";
 import {
   Headers,
   HttpRequestLibrary,
@@ -29,12 +29,26 @@ import {
   HttpResponse,
 } from "./http.js";
 import { RequestThrottler, TalerErrorCode, URL } from "./index.js";
-import { qjsOs } from "./qtart.js";
+import { QjsHttpResp, qjsOs } from "./qtart.js";
 
 const logger = new Logger("http-impl.qtart.ts");
 
 const textDecoder = new TextDecoder();
 
+export class RequestTimeoutError extends Error {
+  public constructor() {
+    super("Request timed out");
+    Object.setPrototypeOf(this, RequestTimeoutError.prototype);
+  }
+}
+
+export class RequestCancelledError extends Error {
+  public constructor() {
+    super("Request cancelled");
+    Object.setPrototypeOf(this, RequestCancelledError.prototype);
+  }
+}
+
 /**
  * Implementation of the HTTP request library interface for node.
  */
@@ -92,12 +106,70 @@ export class HttpLibImpl implements HttpRequestLibrary {
     if (method === "POST") {
       data = encodeBody(opt?.body);
     }
-    const res = await qjsOs.fetchHttp(url, {
+
+    const cancelPromCap = openPromise<QjsHttpResp>();
+
+    // Just like WHATWG fetch(), the qjs http client doesn't
+    // really support cancellation, so cancellation here just
+    // means that the result is ignored!
+    const fetchProm = qjsOs.fetchHttp(url, {
       method,
       data,
       headers: headersList,
     });
 
+    let timeoutHandle: any = undefined;
+    let cancelCancelledHandler: (() => void) | undefined = undefined;
+
+    if (opt?.timeout && opt.timeout.d_ms !== "forever") {
+      timeoutHandle = setTimeout(() => {
+        cancelPromCap.reject(new RequestTimeoutError());
+      }, opt.timeout.d_ms);
+    }
+
+    if (opt?.cancellationToken) {
+      cancelCancelledHandler = opt.cancellationToken.onCancelled(() => {
+        cancelPromCap.reject(new RequestCancelledError());
+      });
+    }
+
+    let res: QjsHttpResp;
+    try {
+      res = await Promise.race([fetchProm, cancelPromCap.promise]);
+    } catch (e) {
+      if (e instanceof RequestCancelledError) {
+        throw TalerError.fromDetail(
+          TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,
+          {
+            requestUrl: url,
+            requestMethod: method,
+            httpStatusCode: 0,
+          },
+          `Request cancelled`,
+        );
+      }
+      if (e instanceof RequestTimeoutError) {
+        throw TalerError.fromDetail(
+          TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,
+          {
+            requestUrl: url,
+            requestMethod: method,
+            httpStatusCode: 0,
+          },
+          `Request timed out`,
+        );
+      }
+      throw e;
+    }
+
+    if (timeoutHandle != null) {
+      clearTimeout(timeoutHandle);
+    }
+
+    if (cancelCancelledHandler != null) {
+      cancelCancelledHandler();
+    }
+
     const headers: Headers = new Headers();
 
     if (res.headers) {
diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts
index 2045a4717..edc9c4ff2 100644
--- a/packages/taler-util/src/index.ts
+++ b/packages/taler-util/src/index.ts
@@ -44,6 +44,7 @@ export {
 export * from "./notifications.js";
 export * from "./operation.js";
 export * from "./payto.js";
+export * from "./promises.js";
 export * from "./rfc3548.js";
 export * from "./taler-crypto.js";
 export * from "./taler-types.js";
diff --git a/packages/taler-util/src/wallet-types.ts 
b/packages/taler-util/src/wallet-types.ts
index b79bfe4fe..e6a66ac9d 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -1927,7 +1927,7 @@ export const codecForSharePaymentResult = (): 
Codec<SharePaymentResult> =>
 
 export interface PreparePayTemplateRequest {
   talerPayTemplateUri: string;
-  templateParams: Record<string, string>;
+  templateParams?: Record<string, string>;
 }
 
 export const codecForPreparePayTemplateRequest =
diff --git a/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts 
b/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts
index 192e9cda1..83897f331 100644
--- a/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts
+++ b/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts
@@ -23,10 +23,14 @@
 /**
  * Imports.
  */
-import { j2s, Logger, TalerErrorCode } from "@gnu-taler/taler-util";
-import { TalerError } from "@gnu-taler/taler-util";
-import { openPromise } from "../../util/promiseUtils.js";
-import { timer, performanceNow, TimerHandle } from "../../util/timer.js";
+import {
+  j2s,
+  Logger,
+  openPromise,
+  TalerError,
+  TalerErrorCode,
+} from "@gnu-taler/taler-util";
+import { performanceNow, timer, TimerHandle } from "../../util/timer.js";
 import { nullCrypto, TalerCryptoInterface } from "../cryptoImplementation.js";
 import { CryptoWorker } from "./cryptoWorkerInterface.js";
 
diff --git a/packages/taler-wallet-core/src/index.ts 
b/packages/taler-wallet-core/src/index.ts
index 643d65620..0eca64d1f 100644
--- a/packages/taler-wallet-core/src/index.ts
+++ b/packages/taler-wallet-core/src/index.ts
@@ -19,7 +19,6 @@
  */
 
 // Util functionality
-export * from "./util/promiseUtils.js";
 export * from "./util/query.js";
 
 export * from "./versions.js";
diff --git a/packages/taler-wallet-core/src/internal-wallet-state.ts 
b/packages/taler-wallet-core/src/internal-wallet-state.ts
index 4379f20b5..13578adda 100644
--- a/packages/taler-wallet-core/src/internal-wallet-state.ts
+++ b/packages/taler-wallet-core/src/internal-wallet-state.ts
@@ -39,7 +39,6 @@ import { HttpRequestLibrary } from 
"@gnu-taler/taler-util/http";
 import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
 import { WalletStoresV1 } from "./db.js";
 import { TaskScheduler } from "./shepherd.js";
-import { AsyncCondition } from "./util/promiseUtils.js";
 import {
   DbAccess,
   GetReadOnlyAccess,
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts 
b/packages/taler-wallet-core/src/operations/exchanges.ts
index 3f8126dba..460b47e73 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -27,6 +27,7 @@ import {
   AbsoluteTime,
   AgeRestriction,
   Amounts,
+  AsyncFlag,
   CancellationToken,
   CoinRefreshRequest,
   CoinStatus,
@@ -95,7 +96,6 @@ import {
   WalletStoresV1,
 } from "../db.js";
 import {
-  AsyncFlag,
   ExchangeEntryDbRecordStatus,
   ExchangeEntryDbUpdateStatus,
   PendingTaskType,
diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts 
b/packages/taler-wallet-core/src/operations/pay-merchant.ts
index e00432bd0..4b692fe69 100644
--- a/packages/taler-wallet-core/src/operations/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts
@@ -31,6 +31,7 @@ import {
   AmountJson,
   Amounts,
   AmountString,
+  AsyncFlag,
   codecForAbortResponse,
   codecForMerchantContractTerms,
   codecForMerchantOrderRefundPickupResponse,
@@ -103,7 +104,6 @@ import {
   WalletStoresV1,
 } from "../db.js";
 import {
-  AsyncFlag,
   getCandidateWithdrawalDenomsTx,
   PendingTaskType,
   RefundGroupRecord,
@@ -1563,26 +1563,30 @@ export async function preparePayForTemplate(
   ws: InternalWalletState,
   req: PreparePayTemplateRequest,
 ): Promise<PreparePayResult> {
-  const url = parsePayTemplateUri(req.talerPayTemplateUri);
+  const parsedUri = parsePayTemplateUri(req.talerPayTemplateUri);
   const templateDetails: MerchantUsingTemplateDetails = {};
-  if (!url) {
+  if (!parsedUri) {
     throw Error("invalid taler-template URI");
   }
+  logger.trace(`parsed URI: ${j2s(parsedUri)}`);
   if (
-    url.templateParams.amount !== undefined &&
-    typeof url.templateParams.amount === "string"
+    parsedUri.templateParams.amount !== undefined &&
+    typeof parsedUri.templateParams.amount === "string"
   ) {
-    templateDetails.amount = (req.templateParams.amount ??
-      url.templateParams.amount) as AmountString | undefined;
+    templateDetails.amount = (req.templateParams?.amount ??
+      parsedUri.templateParams.amount) as AmountString | undefined;
   }
   if (
-    url.templateParams.summary !== undefined &&
-    typeof url.templateParams.summary === "string"
+    parsedUri.templateParams.summary !== undefined &&
+    typeof parsedUri.templateParams.summary === "string"
   ) {
     templateDetails.summary =
-      req.templateParams.summary ?? url.templateParams.summary;
+      req.templateParams?.summary ?? parsedUri.templateParams.summary;
   }
-  const reqUrl = new URL(`templates/${url.templateId}`, url.merchantBaseUrl);
+  const reqUrl = new URL(
+    `templates/${parsedUri.templateId}`,
+    parsedUri.merchantBaseUrl,
+  );
   const httpReq = await ws.http.fetch(reqUrl.href, {
     method: "POST",
     body: templateDetails,
@@ -1593,7 +1597,7 @@ export async function preparePayForTemplate(
   );
 
   const payUri = stringifyPayUri({
-    merchantBaseUrl: url.merchantBaseUrl,
+    merchantBaseUrl: parsedUri.merchantBaseUrl,
     orderId: resp.order_id,
     sessionId: "",
     claimToken: resp.token,
diff --git a/packages/taler-wallet-core/src/operations/testing.ts 
b/packages/taler-wallet-core/src/operations/testing.ts
index 5902e8362..17863450c 100644
--- a/packages/taler-wallet-core/src/operations/testing.ts
+++ b/packages/taler-wallet-core/src/operations/testing.ts
@@ -38,6 +38,8 @@ import {
   j2s,
   Logger,
   NotificationType,
+  OpenedPromise,
+  openPromise,
   parsePaytoUri,
   PreparePayResultType,
   TalerCorebankApiClient,
@@ -54,11 +56,7 @@ import {
   HttpRequestLibrary,
   readSuccessResponseJsonOrThrow,
 } from "@gnu-taler/taler-util/http";
-import {
-  getRefreshesForTransaction,
-  OpenedPromise,
-  openPromise,
-} from "../index.js";
+import { getRefreshesForTransaction } from "../index.js";
 import { InternalWalletState } from "../internal-wallet-state.js";
 import { checkLogicInvariant } from "../util/invariants.js";
 import { getBalances } from "./balance.js";
diff --git a/packages/taler-wallet-core/src/remote.ts 
b/packages/taler-wallet-core/src/remote.ts
index 164f7cfe9..1ee0e1993 100644
--- a/packages/taler-wallet-core/src/remote.ts
+++ b/packages/taler-wallet-core/src/remote.ts
@@ -19,11 +19,12 @@ import {
   CoreApiResponse,
   j2s,
   Logger,
+  OpenedPromise,
+  openPromise,
   TalerError,
   WalletNotification,
 } from "@gnu-taler/taler-util";
 import { connectRpc, JsonMessage } from "@gnu-taler/taler-util/twrpc";
-import { OpenedPromise, openPromise } from "./index.js";
 import { WalletCoreApiClient } from "./wallet-api-types.js";
 
 const logger = new Logger("remote.ts");
diff --git a/packages/taler-wallet-core/src/shepherd.ts 
b/packages/taler-wallet-core/src/shepherd.ts
index d1648acc7..4aea2d15d 100644
--- a/packages/taler-wallet-core/src/shepherd.ts
+++ b/packages/taler-wallet-core/src/shepherd.ts
@@ -20,6 +20,7 @@
 import { GlobalIDB } from "@gnu-taler/idb-bridge";
 import {
   AbsoluteTime,
+  AsyncCondition,
   CancellationToken,
   Duration,
   Logger,
@@ -66,7 +67,6 @@ import { processRefreshGroup } from "./operations/refresh.js";
 import { constructTransactionIdentifier } from "./operations/transactions.js";
 import { processWithdrawalGroup } from "./operations/withdraw.js";
 import { PendingTaskType, TaskId } from "./pending-types.js";
-import { AsyncCondition } from "./util/promiseUtils.js";
 
 const logger = new Logger("shepherd.ts");
 
diff --git a/packages/taler-wallet-core/src/util/promiseUtils.ts 
b/packages/taler-wallet-core/src/util/promiseUtils.ts
deleted file mode 100644
index bc1e40260..000000000
--- a/packages/taler-wallet-core/src/util/promiseUtils.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2019 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- * An opened promise.
- *
- * @see {@link openPromise}
- */
-export interface OpenedPromise<T> {
-  promise: Promise<T>;
-  resolve: (val: T) => void;
-  reject: (err: any) => void;
-  lastError?: any;
-}
-
-/**
- * Get an unresolved promise together with its extracted resolve / reject
- * function.
- *
- * Recent ECMAScript proposals also call this a promise capability.
- */
-export function openPromise<T>(): OpenedPromise<T> {
-  let resolve: ((x?: any) => void) | null = null;
-  let promiseReject: ((reason?: any) => void) | null = null;
-  const promise = new Promise<T>((res, rej) => {
-    resolve = res;
-    promiseReject = rej;
-  });
-  if (!(resolve && promiseReject)) {
-    // Never happens, unless JS implementation is broken
-    throw Error("JS implementation is broken");
-  }
-  const result: OpenedPromise<T> = { resolve, reject: promiseReject, promise };
-  function saveLastError(reason?: any) {
-    result.lastError = reason;
-    promiseReject!(reason);
-  }
-  result.reject = saveLastError;
-  return result;
-}
-
-export class AsyncCondition {
-  private promCap?: OpenedPromise<void> = undefined;
-  constructor() {}
-
-  wait(): Promise<void> {
-    if (!this.promCap) {
-      this.promCap = openPromise<void>();
-    }
-    return this.promCap.promise;
-  }
-
-  trigger(): void {
-    if (this.promCap) {
-      this.promCap.resolve();
-    }
-    this.promCap = undefined;
-  }
-}
-
-/**
- * Flag that can be raised to notify asynchronous waiters.
- *
- * You can think of it as a promise that can
- * be un-resolved.
- */
-export class AsyncFlag {
-  private promCap?: OpenedPromise<void> = undefined;
-  private internalFlagRaised: boolean = false;
-
-  constructor() {}
-
-  /**
-   * Wait until the flag is raised.
-   *
-   * Reset if before returning.
-   */
-  wait(): Promise<void> {
-    if (this.internalFlagRaised) {
-      return Promise.resolve();
-    }
-    if (!this.promCap) {
-      this.promCap = openPromise<void>();
-    }
-    return this.promCap.promise;
-  }
-
-  raise(): void {
-    this.internalFlagRaised = true;
-    if (this.promCap) {
-      this.promCap.resolve();
-    }
-  }
-
-  reset(): void {
-    this.internalFlagRaised = false;
-    this.promCap = undefined;
-  }
-}
diff --git a/packages/taler-wallet-core/src/util/query.ts 
b/packages/taler-wallet-core/src/util/query.ts
index 5fba61f11..19fa0dbfd 100644
--- a/packages/taler-wallet-core/src/util/query.ts
+++ b/packages/taler-wallet-core/src/util/query.ts
@@ -34,8 +34,7 @@ import {
   IDBValidKey,
   IDBVersionChangeEvent,
 } from "@gnu-taler/idb-bridge";
-import { Codec, Logger } from "@gnu-taler/taler-util";
-import { openPromise } from "./promiseUtils.js";
+import { Codec, Logger, openPromise } from "@gnu-taler/taler-util";
 
 const logger = new Logger("query.ts");
 
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index 0246597be..cfe171bd0 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -26,6 +26,7 @@ import { IDBFactory } from "@gnu-taler/idb-bridge";
 import {
   AmountString,
   Amounts,
+  AsyncCondition,
   CoinDumpJson,
   CoinStatus,
   CoreApiResponse,
@@ -40,6 +41,7 @@ import {
   ListGlobalCurrencyAuditorsResponse,
   ListGlobalCurrencyExchangesResponse,
   Logger,
+  OpenedPromise,
   PrepareWithdrawExchangeRequest,
   PrepareWithdrawExchangeResponse,
   RecoverStoredBackupRequest,
@@ -122,6 +124,7 @@ import {
   codecForWithdrawTestBalance,
   getErrorDetailFromException,
   j2s,
+  openPromise,
   parsePaytoUri,
   parseTalerUri,
   sampleWalletCoreTransactions,
@@ -265,11 +268,6 @@ import {
   getMaxPeerPushAmount,
 } from "./util/instructedAmountConversion.js";
 import { checkDbInvariant } from "./util/invariants.js";
-import {
-  AsyncCondition,
-  OpenedPromise,
-  openPromise,
-} from "./util/promiseUtils.js";
 import {
   DbAccess,
   GetReadOnlyAccess,
diff --git a/packages/taler-wallet-embedded/src/wallet-qjs.ts 
b/packages/taler-wallet-embedded/src/wallet-qjs.ts
index 0296dfeb6..0fbcd7583 100644
--- a/packages/taler-wallet-embedded/src/wallet-qjs.ts
+++ b/packages/taler-wallet-embedded/src/wallet-qjs.ts
@@ -39,6 +39,7 @@ import {
   enableNativeLogging,
   getErrorDetailFromException,
   j2s,
+  openPromise,
   setGlobalLogLevelFromString,
 } from "@gnu-taler/taler-util";
 import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
@@ -48,7 +49,6 @@ import {
   Wallet,
   WalletApiOperation,
   createNativeWalletHost2,
-  openPromise,
   performanceNow,
 } from "@gnu-taler/taler-wallet-core";
 
@@ -277,6 +277,7 @@ export async function testWithGv() {
     corebankApiBaseUrl: "https://bank.demo.taler.net/";,
     exchangeBaseUrl: "https://exchange.demo.taler.net/";,
     merchantBaseUrl: "https://backend.demo.taler.net/";,
+    merchantAuthToken: "secret-token:sandbox",
   });
   await w.wallet.runTaskLoop({
     stopWhenDone: true,

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