harness: parallelize service startup

This commit is contained in:
Florian Dold 2023-08-23 17:04:17 +02:00
parent 7fbe28e640
commit ec3ae6f5e3
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
2 changed files with 83 additions and 50 deletions

View File

@ -540,7 +540,7 @@ function backoffStart(): number {
} }
function backoffIncrement(n: number): 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; return;
} catch (e: any) { } catch (e: any) {
logger.warn(`service ${serviceName} not ready:`, e.toString()); logger.warn(`service ${serviceName} not ready:`, e.toString());
//console.log(e); logger.info(`waiting ${nextDelay}ms`);
await delayMs(nextDelay); await delayMs(nextDelay);
nextDelay = backoffIncrement(nextDelay); nextDelay = backoffIncrement(nextDelay);
} }
@ -1535,15 +1535,20 @@ export class ExchangeService implements ExchangeServiceInterface {
); );
} }
async start(): Promise<void> { async start(opts: { skipSetup?: boolean } = {}): Promise<void> {
if (this.isRunning()) { if (this.isRunning()) {
throw Error("exchange is already running"); throw Error("exchange is already running");
} }
const skipSetup = opts.skipSetup ?? false;
if (!skipSetup) {
await sh( await sh(
this.globalState, this.globalState,
"exchange-dbinit", "exchange-dbinit",
`taler-exchange-dbinit -c "${this.configFilename}"`, `taler-exchange-dbinit -c "${this.configFilename}"`,
); );
}
this.helperCryptoEddsaProc = this.globalState.spawnService( this.helperCryptoEddsaProc = this.globalState.spawnService(
"taler-exchange-secmod-eddsa", "taler-exchange-secmod-eddsa",
@ -1574,7 +1579,11 @@ export class ExchangeService implements ExchangeServiceInterface {
); );
await this.pingUntilAvailable(); await this.pingUntilAvailable();
if (!skipSetup) {
await this.keyup(); await this.keyup();
} else {
logger.info("skipping keyup");
}
} }
async pingUntilAvailable(): Promise<void> { async pingUntilAvailable(): Promise<void> {
@ -1912,13 +1921,17 @@ export class MerchantService implements MerchantServiceInterface {
} }
} }
async start(): Promise<void> { async start(opts: { skipSetup?: boolean } = {}): Promise<void> {
const skipSetup = opts.skipSetup ?? false;
if (!skipSetup) {
await runCommand( await runCommand(
this.globalState, this.globalState,
"merchant-dbinit", "merchant-dbinit",
"taler-merchant-dbinit", "taler-merchant-dbinit",
["-c", this.configFilename], ["-c", this.configFilename],
); );
}
this.proc = this.globalState.spawnService( this.proc = this.globalState.spawnService(
"taler-merchant-httpd", "taler-merchant-httpd",
@ -2285,12 +2298,14 @@ export class WalletService {
} }
async pingUntilAvailable(): Promise<void> { async pingUntilAvailable(): Promise<void> {
let nextDelay = backoffStart();
while (1) { while (1) {
try { try {
await tryUnixConnect(this.socketPath); await tryUnixConnect(this.socketPath);
} catch (e) { } catch (e) {
logger.info(`connection attempt failed: ${e}`); logger.info(`connection attempt failed: ${e}`);
await delayMs(200); await delayMs(nextDelay);
nextDelay = backoffIncrement(nextDelay);
continue; continue;
} }
logger.info("connection to wallet-core succeeded"); logger.info("connection to wallet-core succeeded");

View File

@ -218,9 +218,6 @@ export async function createSimpleTestkudosEnvironment(
export async function useSharedTestkudosEnvironment(t: GlobalTestState) { export async function useSharedTestkudosEnvironment(t: GlobalTestState) {
const coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS")); 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}`; const sharedDir = `/tmp/taler-harness@${process.env.USER}`;
fs.mkdirSync(sharedDir, { recursive: true }); 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; let merchant: MerchantService;
const merchantName = "testmerchant-1"; const merchantName = "testmerchant-1";
@ -308,16 +305,26 @@ export async function useSharedTestkudosEnvironment(t: GlobalTestState) {
logger.info("basic setup done, starting services"); logger.info("basic setup done, starting services");
const bankStart = async () => {
await bank.start(); await bank.start();
await bank.pingUntilAvailable(); await bank.pingUntilAvailable();
};
await exchange.start(); const exchangeStart = async () => {
await exchange.start({
skipSetup: prevSetupDone,
});
await exchange.pingUntilAvailable(); await exchange.pingUntilAvailable();
};
await merchant.start(); const merchStart = async () => {
await merchant.start({
skipSetup: prevSetupDone,
});
await merchant.pingUntilAvailable(); await merchant.pingUntilAvailable();
if (!prevSetupDone) {
await merchant.addInstance({ await merchant.addInstance({
id: "default", id: "default",
name: "Default Instance", name: "Default Instance",
@ -335,11 +342,22 @@ export async function useSharedTestkudosEnvironment(t: GlobalTestState) {
Duration.fromSpec({ minutes: 1 }), Duration.fromSpec({ minutes: 1 }),
), ),
}); });
}
};
const { walletClient, walletService } = await createWalletDaemonWithClient( const walletStart = async () => {
t, return await createWalletDaemonWithClient(t, { name: "wallet" });
{ 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!"); console.log("setup done!");
@ -399,7 +417,7 @@ export async function createSimpleTestkudosEnvironmentV2(
bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri); bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
if (opts.additionalBankConfig) { if (opts.additionalBankConfig) {
opts.additionalBankConfig(bank) opts.additionalBankConfig(bank);
} }
await bank.start(); await bank.start();
@ -428,7 +446,7 @@ export async function createSimpleTestkudosEnvironmentV2(
} }
if (opts.additionalExchangeConfig) { if (opts.additionalExchangeConfig) {
opts.additionalExchangeConfig(exchange) opts.additionalExchangeConfig(exchange);
} }
await exchange.start(); await exchange.start();
await exchange.pingUntilAvailable(); await exchange.pingUntilAvailable();
@ -436,7 +454,7 @@ export async function createSimpleTestkudosEnvironmentV2(
merchant.addExchange(exchange); merchant.addExchange(exchange);
if (opts.additionalMerchantConfig) { if (opts.additionalMerchantConfig) {
opts.additionalMerchantConfig(merchant) opts.additionalMerchantConfig(merchant);
} }
await merchant.start(); await merchant.start();
await merchant.pingUntilAvailable(); await merchant.pingUntilAvailable();