diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts index f5782ab09..f6c8ae61e 100644 --- a/packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts +++ b/packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts @@ -23,7 +23,7 @@ * Imports. */ import { Logger } from "@gnu-taler/taler-util"; -import * as timer from "../../util/timer.js"; +import { timer, performanceNow, TimerHandle } from "../../util/timer.js"; import { nullCrypto, TalerCryptoInterface } from "../cryptoImplementation.js"; import { CryptoWorker } from "./cryptoWorkerInterface.js"; @@ -46,7 +46,7 @@ interface WorkerState { /** * Timer to terminate the worker if it's not busy enough. */ - idleTimeoutHandle: timer.TimerHandle | null; + idleTimeoutHandle: TimerHandle | null; } interface WorkItem { @@ -166,7 +166,7 @@ export class CryptoDispatcher { operation: work.operation, }; this.resetWorkerTimeout(ws); - work.startTime = timer.performanceNow(); + work.startTime = performanceNow(); timer.after(0, () => worker.postMessage(msg)); } diff --git a/packages/taler-wallet-core/src/headless/helpers.ts b/packages/taler-wallet-core/src/headless/helpers.ts index 7bc8235fd..180d19859 100644 --- a/packages/taler-wallet-core/src/headless/helpers.ts +++ b/packages/taler-wallet-core/src/headless/helpers.ts @@ -36,6 +36,7 @@ import { NodeThreadCryptoWorkerFactory } from "../crypto/workers/nodeThreadWorke import { SynchronousCryptoWorkerFactory } from "../crypto/workers/synchronousWorkerFactory.js"; import { openTalerDatabase } from "../db-utils.js"; import { HttpRequestLibrary } from "../util/http.js"; +import { SetTimeoutTimerAPI } from "../util/timer.js"; import { Wallet } from "../wallet.js"; import { NodeHttpLib } from "./NodeHttpLib.js"; @@ -176,7 +177,10 @@ export async function getDefaultNodeWallet2( workerFactory = new SynchronousCryptoWorkerFactory(); } } - const w = await Wallet.create(myDb, myHttpLib, workerFactory); + + const timer = new SetTimeoutTimerAPI() + + const w = await Wallet.create(myDb, myHttpLib, timer, workerFactory); if (args.notifyHandler) { w.addNotificationListener(args.notifyHandler); diff --git a/packages/taler-wallet-core/src/util/timer.ts b/packages/taler-wallet-core/src/util/timer.ts index d9fe3439b..c850c663c 100644 --- a/packages/taler-wallet-core/src/util/timer.ts +++ b/packages/taler-wallet-core/src/util/timer.ts @@ -42,7 +42,7 @@ export interface TimerHandle { } class IntervalHandle { - constructor(public h: any) {} + constructor(public h: any) { } clear(): void { clearInterval(this.h); @@ -60,7 +60,7 @@ class IntervalHandle { } class TimeoutHandle { - constructor(public h: any) {} + constructor(public h: any) { } clear(): void { clearTimeout(this.h); @@ -97,20 +97,6 @@ export const performanceNow: () => bigint = (() => { return () => BigInt(0); })(); -/** - * Call a function every time the delay given in milliseconds passes. - */ -export function every(delayMs: number, callback: () => void): TimerHandle { - return new IntervalHandle(setInterval(callback, delayMs)); -} - -/** - * Call a function after the delay given in milliseconds passes. - */ -export function after(delayMs: number, callback: () => void): TimerHandle { - return new TimeoutHandle(setTimeout(callback, delayMs)); -} - const nullTimerHandle = { clear() { // do nothing @@ -125,13 +111,43 @@ const nullTimerHandle = { /** * Group of timers that can be destroyed at once. */ +export interface TimerAPI { + after(delayMs: number, callback: () => void): TimerHandle; + every(delayMs: number, callback: () => void): TimerHandle; +} + +export class SetTimeoutTimerAPI implements TimerAPI { + /** + * Call a function every time the delay given in milliseconds passes. + */ + every(delayMs: number, callback: () => void): TimerHandle { + return new IntervalHandle(setInterval(callback, delayMs)); + } + + /** + * Call a function after the delay given in milliseconds passes. + */ + after(delayMs: number, callback: () => void): TimerHandle { + return new TimeoutHandle(setTimeout(callback, delayMs)); + } + + +} + +export const timer = new SetTimeoutTimerAPI(); + +/** + * Implementation of [[TimerGroup]] using setTimeout + */ export class TimerGroup { private stopped = false; - private timerMap: { [index: number]: TimerHandle } = {}; + private readonly timerMap: { [index: number]: TimerHandle } = {}; private idGen = 1; + constructor(public readonly timerApi: TimerAPI) { } + stopCurrentAndFutureTimers(): void { this.stopped = true; for (const x in this.timerMap) { @@ -158,7 +174,7 @@ export class TimerGroup { logger.warn("dropping timer since timer group is stopped"); return nullTimerHandle; } - const h = after(delayMs, callback); + const h = this.timerApi.after(delayMs, callback); const myId = this.idGen++; this.timerMap[myId] = h; @@ -180,7 +196,7 @@ export class TimerGroup { logger.warn("dropping timer since timer group is stopped"); return nullTimerHandle; } - const h = every(delayMs, callback); + const h = this.timerApi.every(delayMs, callback); const myId = this.idGen++; this.timerMap[myId] = h; diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 673a86167..e17bbb805 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -192,7 +192,7 @@ import { openPromise, } from "./util/promiseUtils.js"; import { DbAccess, GetReadWriteAccess } from "./util/query.js"; -import { TimerGroup } from "./util/timer.js"; +import { TimerAPI, TimerGroup } from "./util/timer.js"; import { WalletCoreApiClient } from "./wallet-api-types.js"; import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js"; @@ -1080,9 +1080,10 @@ export class Wallet { private constructor( db: DbAccess, http: HttpRequestLibrary, + timer: TimerAPI, cryptoWorkerFactory: CryptoWorkerFactory, ) { - this.ws = new InternalWalletStateImpl(db, http, cryptoWorkerFactory); + this.ws = new InternalWalletStateImpl(db, http, timer, cryptoWorkerFactory); } get client(): WalletCoreApiClient { @@ -1100,9 +1101,10 @@ export class Wallet { static async create( db: DbAccess, http: HttpRequestLibrary, + timer: TimerAPI, cryptoWorkerFactory: CryptoWorkerFactory, ): Promise { - const w = new Wallet(db, http, cryptoWorkerFactory); + const w = new Wallet(db, http, timer, cryptoWorkerFactory); w._client = await getClientFromWalletState(w.ws); return w; } @@ -1153,7 +1155,7 @@ class InternalWalletStateImpl implements InternalWalletState { insecureTrustExchange = false; - timerGroup: TimerGroup = new TimerGroup(); + readonly timerGroup: TimerGroup; latch = new AsyncCondition(); stopped = false; @@ -1200,10 +1202,12 @@ class InternalWalletStateImpl implements InternalWalletState { // and throw an error in that case. public db: DbAccess, public http: HttpRequestLibrary, + public timer: TimerAPI, cryptoWorkerFactory: CryptoWorkerFactory, ) { this.cryptoDispatcher = new CryptoDispatcher(cryptoWorkerFactory); this.cryptoApi = this.cryptoDispatcher.cryptoApi; + this.timerGroup = new TimerGroup(timer) } async getDenomInfo(