datahaven/test/utils/parameters.ts
Ahmad Kaouk 9344e243cf
perf: Batch runtime parameter updates to speed up E2E setup (#368)
## Summary
Optimizes the DataHaven parameter configuration during E2E test
infrastructure setup by batching multiple extrinsics into a single
transaction, reducing setup time.
## Problem
Setting runtime parameters required 5 separate
`Parameters.set_parameter` calls, each waiting for block finality. This
created unnecessary delays during infrastructure setup since each call
blocked sequentially.
## Solution
- **Batch parameter updates:** Combine all `Parameters.set_parameter
`calls into a single `Utility.batch_all` transaction wrapped in
`Sudo.sudo`.
- **~5× faster parameter setup:** Only wait for finality once instead of
5 separate times
- **Code simplification:** Refactored parameter handling code, removing
~190 lines of unnecessary abstractions and complexity
2025-12-22 15:57:32 +01:00

92 lines
3.2 KiB
TypeScript

import path from "node:path";
import { $ } from "bun";
import { logger } from "./logger";
import type { DataHavenRuntimeParameterKey } from "./types";
/** Raw parameter for JSON storage (hex strings, not FixedSizeBinary) */
interface RawParameter {
name: DataHavenRuntimeParameterKey;
value: string | null | undefined;
}
// Constants for paths
export const PARAMETERS_TEMPLATE_PATH = "configs/parameters/datahaven-parameters.json";
export const PARAMETERS_OUTPUT_DIR = "tmp/configs";
export const PARAMETERS_OUTPUT_FILE = "datahaven-parameters.json";
export const PARAMETERS_OUTPUT_PATH = path.join(PARAMETERS_OUTPUT_DIR, PARAMETERS_OUTPUT_FILE);
/**
* A collection of parameters to be set in the DataHaven runtime.
* This class is used to collect parameters from different steps of the launch process
* and then generate a JSON file to be used by the setDataHavenParameters script.
*/
export class ParameterCollection {
private parameters: RawParameter[] = [];
/**
* Adds a parameter to the collection
* @param param The parameter to add
*/
public addParameter(param: RawParameter): void {
// Check if parameter with same name already exists
const existingIndex = this.parameters.findIndex((p) => p.name === param.name);
if (existingIndex !== -1) {
// Replace existing parameter
this.parameters[existingIndex] = param;
logger.debug(`Updated parameter: ${String(param.name)} = ${JSON.stringify(param.value)}`);
} else {
// Add new parameter
this.parameters.push(param);
logger.debug(`Added parameter: ${String(param.name)} = ${JSON.stringify(param.value)}`);
}
}
/**
* Returns the current parameters
*/
public getParameters(): RawParameter[] {
return [...this.parameters];
}
/**
* Generates a JSON file with the parameters collected so far
*/
public async generateParametersFile(): Promise<string> {
logger.debug(`Ensuring output directory exists: ${PARAMETERS_OUTPUT_DIR}`);
await $`mkdir -p ${PARAMETERS_OUTPUT_DIR}`.quiet();
// If we have no parameters, load the template to get the structure
if (this.parameters.length === 0) {
logger.debug(`No parameters collected, loading template from ${PARAMETERS_TEMPLATE_PATH}`);
const templateFile = Bun.file(PARAMETERS_TEMPLATE_PATH);
if (!(await templateFile.exists())) {
throw new Error(`Template file ${PARAMETERS_TEMPLATE_PATH} does not exist`);
}
this.parameters = await templateFile.json();
}
// Write the parameters to a file
logger.debug(`Writing parameters to ${PARAMETERS_OUTPUT_PATH}`);
await Bun.write(PARAMETERS_OUTPUT_PATH, JSON.stringify(this.parameters, null, 2));
logger.debug(`Parameters file generated at ${PARAMETERS_OUTPUT_PATH}`);
return PARAMETERS_OUTPUT_PATH;
}
}
/**
* Creates a new ParameterCollection, pre-loaded with template parameters if available
*/
export const createParameterCollection = async (): Promise<ParameterCollection> => {
const collection = new ParameterCollection();
const templateFile = Bun.file(PARAMETERS_TEMPLATE_PATH);
if (await templateFile.exists()) {
const templateParams = await templateFile.json();
for (const param of templateParams) {
collection.addParameter(param);
}
}
return collection;
};