add a timer parameter in the wallet constructor in order to resolve #7120

This commit is contained in:
Sebastian 2022-04-11 15:10:16 -03:00
parent ccb50c6360
commit a644efe1ab
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
4 changed files with 51 additions and 27 deletions

View File

@ -23,7 +23,7 @@
* Imports. * Imports.
*/ */
import { Logger } from "@gnu-taler/taler-util"; 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 { nullCrypto, TalerCryptoInterface } from "../cryptoImplementation.js";
import { CryptoWorker } from "./cryptoWorkerInterface.js"; import { CryptoWorker } from "./cryptoWorkerInterface.js";
@ -46,7 +46,7 @@ interface WorkerState {
/** /**
* Timer to terminate the worker if it's not busy enough. * Timer to terminate the worker if it's not busy enough.
*/ */
idleTimeoutHandle: timer.TimerHandle | null; idleTimeoutHandle: TimerHandle | null;
} }
interface WorkItem { interface WorkItem {
@ -166,7 +166,7 @@ export class CryptoDispatcher {
operation: work.operation, operation: work.operation,
}; };
this.resetWorkerTimeout(ws); this.resetWorkerTimeout(ws);
work.startTime = timer.performanceNow(); work.startTime = performanceNow();
timer.after(0, () => worker.postMessage(msg)); timer.after(0, () => worker.postMessage(msg));
} }

View File

@ -36,6 +36,7 @@ import { NodeThreadCryptoWorkerFactory } from "../crypto/workers/nodeThreadWorke
import { SynchronousCryptoWorkerFactory } from "../crypto/workers/synchronousWorkerFactory.js"; import { SynchronousCryptoWorkerFactory } from "../crypto/workers/synchronousWorkerFactory.js";
import { openTalerDatabase } from "../db-utils.js"; import { openTalerDatabase } from "../db-utils.js";
import { HttpRequestLibrary } from "../util/http.js"; import { HttpRequestLibrary } from "../util/http.js";
import { SetTimeoutTimerAPI } from "../util/timer.js";
import { Wallet } from "../wallet.js"; import { Wallet } from "../wallet.js";
import { NodeHttpLib } from "./NodeHttpLib.js"; import { NodeHttpLib } from "./NodeHttpLib.js";
@ -176,7 +177,10 @@ export async function getDefaultNodeWallet2(
workerFactory = new SynchronousCryptoWorkerFactory(); 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) { if (args.notifyHandler) {
w.addNotificationListener(args.notifyHandler); w.addNotificationListener(args.notifyHandler);

View File

@ -42,7 +42,7 @@ export interface TimerHandle {
} }
class IntervalHandle { class IntervalHandle {
constructor(public h: any) {} constructor(public h: any) { }
clear(): void { clear(): void {
clearInterval(this.h); clearInterval(this.h);
@ -60,7 +60,7 @@ class IntervalHandle {
} }
class TimeoutHandle { class TimeoutHandle {
constructor(public h: any) {} constructor(public h: any) { }
clear(): void { clear(): void {
clearTimeout(this.h); clearTimeout(this.h);
@ -97,20 +97,6 @@ export const performanceNow: () => bigint = (() => {
return () => BigInt(0); 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 = { const nullTimerHandle = {
clear() { clear() {
// do nothing // do nothing
@ -125,13 +111,43 @@ const nullTimerHandle = {
/** /**
* Group of timers that can be destroyed at once. * 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 { export class TimerGroup {
private stopped = false; private stopped = false;
private timerMap: { [index: number]: TimerHandle } = {}; private readonly timerMap: { [index: number]: TimerHandle } = {};
private idGen = 1; private idGen = 1;
constructor(public readonly timerApi: TimerAPI) { }
stopCurrentAndFutureTimers(): void { stopCurrentAndFutureTimers(): void {
this.stopped = true; this.stopped = true;
for (const x in this.timerMap) { for (const x in this.timerMap) {
@ -158,7 +174,7 @@ export class TimerGroup {
logger.warn("dropping timer since timer group is stopped"); logger.warn("dropping timer since timer group is stopped");
return nullTimerHandle; return nullTimerHandle;
} }
const h = after(delayMs, callback); const h = this.timerApi.after(delayMs, callback);
const myId = this.idGen++; const myId = this.idGen++;
this.timerMap[myId] = h; this.timerMap[myId] = h;
@ -180,7 +196,7 @@ export class TimerGroup {
logger.warn("dropping timer since timer group is stopped"); logger.warn("dropping timer since timer group is stopped");
return nullTimerHandle; return nullTimerHandle;
} }
const h = every(delayMs, callback); const h = this.timerApi.every(delayMs, callback);
const myId = this.idGen++; const myId = this.idGen++;
this.timerMap[myId] = h; this.timerMap[myId] = h;

View File

@ -192,7 +192,7 @@ import {
openPromise, openPromise,
} from "./util/promiseUtils.js"; } from "./util/promiseUtils.js";
import { DbAccess, GetReadWriteAccess } from "./util/query.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 { WalletCoreApiClient } from "./wallet-api-types.js";
import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js"; import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
@ -1080,9 +1080,10 @@ export class Wallet {
private constructor( private constructor(
db: DbAccess<typeof WalletStoresV1>, db: DbAccess<typeof WalletStoresV1>,
http: HttpRequestLibrary, http: HttpRequestLibrary,
timer: TimerAPI,
cryptoWorkerFactory: CryptoWorkerFactory, cryptoWorkerFactory: CryptoWorkerFactory,
) { ) {
this.ws = new InternalWalletStateImpl(db, http, cryptoWorkerFactory); this.ws = new InternalWalletStateImpl(db, http, timer, cryptoWorkerFactory);
} }
get client(): WalletCoreApiClient { get client(): WalletCoreApiClient {
@ -1100,9 +1101,10 @@ export class Wallet {
static async create( static async create(
db: DbAccess<typeof WalletStoresV1>, db: DbAccess<typeof WalletStoresV1>,
http: HttpRequestLibrary, http: HttpRequestLibrary,
timer: TimerAPI,
cryptoWorkerFactory: CryptoWorkerFactory, cryptoWorkerFactory: CryptoWorkerFactory,
): Promise<Wallet> { ): Promise<Wallet> {
const w = new Wallet(db, http, cryptoWorkerFactory); const w = new Wallet(db, http, timer, cryptoWorkerFactory);
w._client = await getClientFromWalletState(w.ws); w._client = await getClientFromWalletState(w.ws);
return w; return w;
} }
@ -1153,7 +1155,7 @@ class InternalWalletStateImpl implements InternalWalletState {
insecureTrustExchange = false; insecureTrustExchange = false;
timerGroup: TimerGroup = new TimerGroup(); readonly timerGroup: TimerGroup;
latch = new AsyncCondition(); latch = new AsyncCondition();
stopped = false; stopped = false;
@ -1200,10 +1202,12 @@ class InternalWalletStateImpl implements InternalWalletState {
// and throw an error in that case. // and throw an error in that case.
public db: DbAccess<typeof WalletStoresV1>, public db: DbAccess<typeof WalletStoresV1>,
public http: HttpRequestLibrary, public http: HttpRequestLibrary,
public timer: TimerAPI,
cryptoWorkerFactory: CryptoWorkerFactory, cryptoWorkerFactory: CryptoWorkerFactory,
) { ) {
this.cryptoDispatcher = new CryptoDispatcher(cryptoWorkerFactory); this.cryptoDispatcher = new CryptoDispatcher(cryptoWorkerFactory);
this.cryptoApi = this.cryptoDispatcher.cryptoApi; this.cryptoApi = this.cryptoDispatcher.cryptoApi;
this.timerGroup = new TimerGroup(timer)
} }
async getDenomInfo( async getDenomInfo(