forked from TrueCloudLab/xk6-frostfs
Vladimir Domnich
b1ec6d562c
At the moment we don't need logic that swings back to beginning of registry when all objects have been processed. So, for now we can stop iterating and return an error when selector reaches the end of registry. Signed-off-by: Vladimir Domnich <v.domnich@yadro.com>
111 lines
3.5 KiB
JavaScript
111 lines
3.5 KiB
JavaScript
import native from 'k6/x/neofs/native';
|
|
import registry from 'k6/x/neofs/registry';
|
|
import s3 from 'k6/x/neofs/s3';
|
|
import { sleep } from 'k6';
|
|
import { Counter } from 'k6/metrics';
|
|
|
|
/*
|
|
./k6 run -e CLIENTS=200 -e TIME_LIMIT=30 -e GRPC_ENDPOINTS=node4.data:8084
|
|
-e REGISTRY_FILE=registry.bolt scenarios/verify.js
|
|
*/
|
|
const obj_registry = registry.open(__ENV.REGISTRY_FILE);
|
|
|
|
// Time limit (in seconds) for the run
|
|
const time_limit = __ENV.TIME_LIMIT || "60";
|
|
|
|
// Count of objects in each status
|
|
const obj_counters = {
|
|
verified: new Counter('verified_obj'),
|
|
skipped: new Counter('skipped_obj'),
|
|
invalid: new Counter('invalid_obj'),
|
|
};
|
|
|
|
// Connect to random gRPC endpoint
|
|
let grpc_client = undefined;
|
|
if (__ENV.GRPC_ENDPOINTS) {
|
|
const grpcEndpoints = __ENV.GRPC_ENDPOINTS.split(',');
|
|
const grpcEndpoint = grpcEndpoints[Math.floor(Math.random() * grpcEndpoints.length)];
|
|
grpc_client = native.connect(grpcEndpoint, '');
|
|
}
|
|
|
|
// Connect to random S3 endpoint
|
|
let s3_client = undefined;
|
|
if (__ENV.S3_ENDPOINTS) {
|
|
const s3_endpoints = __ENV.S3_ENDPOINTS.split(',');
|
|
const s3_endpoint = s3_endpoints[Math.floor(Math.random() * s3_endpoints.length)];
|
|
s3_client = s3.connect(`http://${s3_endpoint}`);
|
|
}
|
|
|
|
// We will attempt to verify every object in "created" status. The scenario will execute
|
|
// as many scenarios as there are objects. Each object will have 3 retries to be verified
|
|
const obj_count_to_verify = obj_registry.getObjectCountInStatus("created");
|
|
// Execute at least one iteration (shared-iterations can't run 0 iterations)
|
|
const iterations = Math.max(1, obj_count_to_verify);
|
|
// Executor shared-iterations requires number of iterations to be larger than number of VUs
|
|
const vus = Math.min(__ENV.CLIENTS, iterations);
|
|
|
|
const scenarios = {
|
|
verify: {
|
|
executor: 'shared-iterations',
|
|
vus,
|
|
iterations,
|
|
maxDuration: `${time_limit}s`,
|
|
exec: 'obj_verify',
|
|
gracefulStop: '5s',
|
|
}
|
|
};
|
|
|
|
export const options = {
|
|
scenarios,
|
|
setupTimeout: '5s',
|
|
};
|
|
|
|
export function setup() {
|
|
// Populate counters with initial values
|
|
for (const [status, counter] of Object.entries(obj_counters)) {
|
|
counter.add(obj_registry.getObjectCountInStatus(status));
|
|
}
|
|
}
|
|
|
|
export function obj_verify() {
|
|
if (__ENV.SLEEP) {
|
|
sleep(__ENV.SLEEP);
|
|
}
|
|
|
|
const obj = obj_registry.nextObjectToVerify();
|
|
if (!obj) {
|
|
console.log("All objects have been verified");
|
|
return;
|
|
}
|
|
console.log(`Verifying object ${obj.id}`);
|
|
|
|
const obj_status = verify_object_with_retries(obj, 3);
|
|
obj_counters[obj_status].add(1);
|
|
obj_registry.setObjectStatus(obj.id, obj_status);
|
|
}
|
|
|
|
function verify_object_with_retries(obj, attempts) {
|
|
for (let i = 0; i < attempts; i++) {
|
|
let result;
|
|
if (obj.c_id && obj.o_id) {
|
|
result = grpc_client.verifyHash(obj.c_id, obj.o_id, obj.payload_hash);
|
|
} else if (obj.s3_bucket && obj.s3_key) {
|
|
result = s3_client.verifyHash(obj.s3_bucket, obj.s3_key, obj.payload_hash);
|
|
} else {
|
|
console.log(`Object id=${obj.id} cannot be verified with supported protocols`);
|
|
return "skipped";
|
|
}
|
|
|
|
if (result.success) {
|
|
return "verified";
|
|
} else if (result.error == "hash mismatch") {
|
|
return "invalid";
|
|
}
|
|
|
|
// Unless we explicitly saw that there was a hash mismatch, then we will retry after a delay
|
|
console.log(`Verify error on ${obj.id}: {resp.error}. Object will be re-tried`);
|
|
sleep(__ENV.SLEEP);
|
|
}
|
|
|
|
return "invalid";
|
|
}
|