xk6-frostfs/scenarios/verify.js

112 lines
3.5 KiB
JavaScript
Raw Normal View History

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";
}