From 61bc36b90aed99d161b28b9bc1742e7e1599546a Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 15 Aug 2019 19:10:23 +0200 Subject: use factory instead of startWorker --- src/crypto/cryptoApi-test.ts | 8 ++-- src/crypto/cryptoApi.ts | 88 ++++++++++++++++++++++++++++++++++++-------- src/crypto/startWorker.js | 41 --------------------- 3 files changed, 76 insertions(+), 61 deletions(-) delete mode 100644 src/crypto/startWorker.js (limited to 'src/crypto') diff --git a/src/crypto/cryptoApi-test.ts b/src/crypto/cryptoApi-test.ts index 6d43e2e6e..9c592412e 100644 --- a/src/crypto/cryptoApi-test.ts +++ b/src/crypto/cryptoApi-test.ts @@ -24,7 +24,7 @@ import { ReserveRecord, } from "../dbTypes"; -import { CryptoApi } from "./cryptoApi"; +import { CryptoApi, NodeCryptoWorkerFactory } from "./cryptoApi"; const masterPub1: string = "CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00"; @@ -73,7 +73,7 @@ const denomInvalid1 = JSON.parse(JSON.stringify(denomValid1)); denomInvalid1.value.value += 1; test("string hashing", async t => { - const crypto = new CryptoApi(); + const crypto = new CryptoApi(new NodeCryptoWorkerFactory()); const s = await crypto.hashString("hello taler"); const sh = "8RDMADB3YNF3QZBS3V467YZVJAMC2QAQX0TZGVZ6Q5PFRRAJFT70HHN0QF661QR9QWKYMMC7YEMPD679D2RADXCYK8Y669A2A5MKQFR"; @@ -82,7 +82,7 @@ test("string hashing", async t => { }); test("precoin creation", async t => { - const crypto = new CryptoApi(); + const crypto = new CryptoApi(new NodeCryptoWorkerFactory()); const { priv, pub } = await crypto.createEddsaKeypair(); const r: ReserveRecord = { created: 0, @@ -103,7 +103,7 @@ test("precoin creation", async t => { }); test("denom validation", async t => { - const crypto = new CryptoApi(); + const crypto = new CryptoApi(new NodeCryptoWorkerFactory()); let v: boolean; v = await crypto.isValidDenom(denomValid1, masterPub1); t.true(v); diff --git a/src/crypto/cryptoApi.ts b/src/crypto/cryptoApi.ts index 5e3237836..accebd651 100644 --- a/src/crypto/cryptoApi.ts +++ b/src/crypto/cryptoApi.ts @@ -39,9 +39,7 @@ import { ContractTerms, PaybackRequest } from "../talerTypes"; import { BenchmarkResult, CoinWithDenom, PayCoinInfo } from "../walletTypes"; import * as timer from "../timer"; - -import { startWorker } from "./startWorker"; -import { throws } from "assert"; +import { string } from "prop-types"; /** * State of a crypto worker. @@ -50,7 +48,7 @@ interface WorkerState { /** * The actual worker thread. */ - w: Worker | null; + w: CryptoWorker | null; /** * Work we're currently executing or null if not busy. @@ -86,6 +84,67 @@ interface WorkItem { */ const NUM_PRIO = 5; +interface CryptoWorker { + postMessage(message: any): void; + + terminate(): void; + + onmessage: (m: any) => void; + onerror: (m: any) => void; +} + +export interface CryptoWorkerFactory { + /** + * Start a new worker. + */ + startWorker(): CryptoWorker; + + /** + * Query the number of workers that should be + * run at the same time. + */ + getConcurrency(): number +} + + +export class NodeCryptoWorkerFactory implements CryptoWorkerFactory { + startWorker(): CryptoWorker { + if (typeof require === "undefined") { + throw Error("cannot make worker, require(...) not defined"); + } + const workerCtor = require("./nodeWorker").Worker; + const workerPath = __dirname + "/cryptoWorker.js"; + return new workerCtor(workerPath); + } + + getConcurrency(): number { + return 2; + } +} + + +export class BrowserCryptoWorkerFactory implements CryptoWorkerFactory { + startWorker(): CryptoWorker { + const workerCtor = Worker; + const workerPath = "/dist/cryptoWorker-bundle.js"; + return new workerCtor(workerPath) as CryptoWorker; + } + + getConcurrency(): number { + let concurrency = 2; + try { + // only works in the browser + // tslint:disable-next-line:no-string-literal + concurrency = (navigator as any)["hardwareConcurrency"]; + concurrency = Math.max(1, Math.ceil(concurrency / 2)); + } catch (e) { + concurrency = 2; + } + return concurrency; + } +} + + /** * Crypto API that interfaces manages a background crypto thread * for the execution of expensive operations. @@ -94,6 +153,9 @@ export class CryptoApi { private nextRpcId: number = 1; private workers: WorkerState[]; private workQueues: WorkItem[][]; + + private workerFactory: CryptoWorkerFactory; + /** * Number of busy workers. */ @@ -106,6 +168,7 @@ export class CryptoApi { public enableTracing = false; + /** * Terminate all worker threads. */ @@ -146,7 +209,7 @@ export class CryptoApi { ws.currentWorkItem = work; this.numBusy++; if (!ws.w) { - const w = startWorker(); + const w = this.workerFactory.startWorker(); w.onmessage = (m: MessageEvent) => this.handleWorkerMessage(ws, m); w.onerror = (e: ErrorEvent) => this.handleWorkerError(ws, e); ws.w = w; @@ -239,17 +302,9 @@ export class CryptoApi { currentWorkItem.resolve(msg.data.result); } - constructor() { - let concurrency = 2; - try { - // only works in the browser - // tslint:disable-next-line:no-string-literal - concurrency = (navigator as any)["hardwareConcurrency"]; - concurrency = Math.max(1, Math.ceil(concurrency / 2)); - } catch (e) { - // ignore - } - this.workers = new Array(concurrency); + constructor(workerFactory: CryptoWorkerFactory) { + this.workerFactory = workerFactory; + this.workers = new Array(workerFactory.getConcurrency()); for (let i = 0; i < this.workers.length; i++) { this.workers[i] = { @@ -258,6 +313,7 @@ export class CryptoApi { w: null, }; } + this.workQueues = []; for (let i = 0; i < NUM_PRIO; i++) { this.workQueues.push([]); diff --git a/src/crypto/startWorker.js b/src/crypto/startWorker.js deleted file mode 100644 index a64152c64..000000000 --- a/src/crypto/startWorker.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - This file is part of TALER - (C) 2017 Inria and 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 - */ - - -// @ts-nocheck - - -/** - * Start a crypto worker, using different worker - * mechanisms depending on the environment. - * - * @returns {Worker} - */ -export function startWorker() { - let workerCtor; - let workerPath; - if (typeof Worker !== "undefined") { - // we're in the browser - workerCtor = Worker; - workerPath = "/dist/cryptoWorker-bundle.js"; - } else if (typeof "require" !== "undefined") { - workerCtor = require("./nodeWorker").Worker; - workerPath = __dirname + "/cryptoWorker.js"; - } else { - throw Error("Can't create worker, unknown environment"); - } - return new workerCtor(workerPath); -} -- cgit v1.2.3