From ec3ae6f5e3f89c13664449bbcbfd2be9a1a6edcc Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 23 Aug 2023 17:04:17 +0200 Subject: [PATCH] harness: parallelize service startup --- packages/taler-harness/src/harness/harness.ts | 49 +++++++---- packages/taler-harness/src/harness/helpers.ts | 84 +++++++++++-------- 2 files changed, 83 insertions(+), 50 deletions(-) diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts index 3a12024dc..8f1f3f452 100644 --- a/packages/taler-harness/src/harness/harness.ts +++ b/packages/taler-harness/src/harness/harness.ts @@ -540,7 +540,7 @@ function backoffStart(): number { } function backoffIncrement(n: number): number { - return Math.max(n * 2, 1000); + return Math.min(Math.floor(n * 1.5), 1000); } /** @@ -563,7 +563,7 @@ export async function pingProc( return; } catch (e: any) { logger.warn(`service ${serviceName} not ready:`, e.toString()); - //console.log(e); + logger.info(`waiting ${nextDelay}ms`); await delayMs(nextDelay); nextDelay = backoffIncrement(nextDelay); } @@ -1535,15 +1535,20 @@ export class ExchangeService implements ExchangeServiceInterface { ); } - async start(): Promise { + async start(opts: { skipSetup?: boolean } = {}): Promise { if (this.isRunning()) { throw Error("exchange is already running"); } - await sh( - this.globalState, - "exchange-dbinit", - `taler-exchange-dbinit -c "${this.configFilename}"`, - ); + + const skipSetup = opts.skipSetup ?? false; + + if (!skipSetup) { + await sh( + this.globalState, + "exchange-dbinit", + `taler-exchange-dbinit -c "${this.configFilename}"`, + ); + } this.helperCryptoEddsaProc = this.globalState.spawnService( "taler-exchange-secmod-eddsa", @@ -1574,7 +1579,11 @@ export class ExchangeService implements ExchangeServiceInterface { ); await this.pingUntilAvailable(); - await this.keyup(); + if (!skipSetup) { + await this.keyup(); + } else { + logger.info("skipping keyup"); + } } async pingUntilAvailable(): Promise { @@ -1912,13 +1921,17 @@ export class MerchantService implements MerchantServiceInterface { } } - async start(): Promise { - await runCommand( - this.globalState, - "merchant-dbinit", - "taler-merchant-dbinit", - ["-c", this.configFilename], - ); + async start(opts: { skipSetup?: boolean } = {}): Promise { + const skipSetup = opts.skipSetup ?? false; + + if (!skipSetup) { + await runCommand( + this.globalState, + "merchant-dbinit", + "taler-merchant-dbinit", + ["-c", this.configFilename], + ); + } this.proc = this.globalState.spawnService( "taler-merchant-httpd", @@ -2285,12 +2298,14 @@ export class WalletService { } async pingUntilAvailable(): Promise { + let nextDelay = backoffStart(); while (1) { try { await tryUnixConnect(this.socketPath); } catch (e) { logger.info(`connection attempt failed: ${e}`); - await delayMs(200); + await delayMs(nextDelay); + nextDelay = backoffIncrement(nextDelay); continue; } logger.info("connection to wallet-core succeeded"); diff --git a/packages/taler-harness/src/harness/helpers.ts b/packages/taler-harness/src/harness/helpers.ts index 9004d4419..932854a1e 100644 --- a/packages/taler-harness/src/harness/helpers.ts +++ b/packages/taler-harness/src/harness/helpers.ts @@ -218,9 +218,6 @@ export async function createSimpleTestkudosEnvironment( export async function useSharedTestkudosEnvironment(t: GlobalTestState) { const coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS")); - // FIXME: We should probably have some file to indicate that - // the previous env setup finished successfully. - const sharedDir = `/tmp/taler-harness@${process.env.USER}`; fs.mkdirSync(sharedDir, { recursive: true }); @@ -270,7 +267,7 @@ export async function useSharedTestkudosEnvironment(t: GlobalTestState) { }); } - logger.info("setting up exchange"); + logger.info("setting up merchant"); let merchant: MerchantService; const merchantName = "testmerchant-1"; @@ -308,38 +305,59 @@ export async function useSharedTestkudosEnvironment(t: GlobalTestState) { logger.info("basic setup done, starting services"); - await bank.start(); + const bankStart = async () => { + await bank.start(); - await bank.pingUntilAvailable(); + await bank.pingUntilAvailable(); + }; - await exchange.start(); - await exchange.pingUntilAvailable(); + const exchangeStart = async () => { + await exchange.start({ + skipSetup: prevSetupDone, + }); + await exchange.pingUntilAvailable(); + }; - await merchant.start(); - await merchant.pingUntilAvailable(); + const merchStart = async () => { + await merchant.start({ + skipSetup: prevSetupDone, + }); + await merchant.pingUntilAvailable(); - await merchant.addInstance({ - id: "default", - name: "Default Instance", - paytoUris: [getPayto("merchant-default")], - defaultWireTransferDelay: Duration.toTalerProtocolDuration( - Duration.fromSpec({ minutes: 1 }), - ), - }); + if (!prevSetupDone) { + await merchant.addInstance({ + id: "default", + name: "Default Instance", + paytoUris: [getPayto("merchant-default")], + defaultWireTransferDelay: Duration.toTalerProtocolDuration( + Duration.fromSpec({ minutes: 1 }), + ), + }); - await merchant.addInstance({ - id: "minst1", - name: "minst1", - paytoUris: [getPayto("minst1")], - defaultWireTransferDelay: Duration.toTalerProtocolDuration( - Duration.fromSpec({ minutes: 1 }), - ), - }); + await merchant.addInstance({ + id: "minst1", + name: "minst1", + paytoUris: [getPayto("minst1")], + defaultWireTransferDelay: Duration.toTalerProtocolDuration( + Duration.fromSpec({ minutes: 1 }), + ), + }); + } + }; - const { walletClient, walletService } = await createWalletDaemonWithClient( - t, - { name: "wallet" }, - ); + const walletStart = async () => { + return await createWalletDaemonWithClient(t, { name: "wallet" }); + }; + + const res = await Promise.all([ + exchangeStart(), + merchStart(), + bankStart(), + walletStart(), + ]); + + const walletClient = res[3].walletClient; + const walletService = res[3].walletService; console.log("setup done!"); @@ -399,7 +417,7 @@ export async function createSimpleTestkudosEnvironmentV2( bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri); if (opts.additionalBankConfig) { - opts.additionalBankConfig(bank) + opts.additionalBankConfig(bank); } await bank.start(); @@ -428,7 +446,7 @@ export async function createSimpleTestkudosEnvironmentV2( } if (opts.additionalExchangeConfig) { - opts.additionalExchangeConfig(exchange) + opts.additionalExchangeConfig(exchange); } await exchange.start(); await exchange.pingUntilAvailable(); @@ -436,7 +454,7 @@ export async function createSimpleTestkudosEnvironmentV2( merchant.addExchange(exchange); if (opts.additionalMerchantConfig) { - opts.additionalMerchantConfig(merchant) + opts.additionalMerchantConfig(merchant); } await merchant.start(); await merchant.pingUntilAvailable();