forked from TrueCloudLab/xk6-frostfs
Vladimir Domnich
37e27f6791
1. Added simple lock mechanism to reset obj selector. This prevents most of concurrency issues when multiple VUs try to reset selector. 2. Added logic to delete objects to grpc and s3 scenarios. 3. Added registry support to http scenario. 4. Deletion logic was not implemented for http scenario, because http gateway does not provide web-method to delete objects. Signed-off-by: Vladimir Domnich <v.domnich@yadro.com>
164 lines
4.6 KiB
JavaScript
164 lines
4.6 KiB
JavaScript
import datagen from 'k6/x/neofs/datagen';
|
|
import native from 'k6/x/neofs/native';
|
|
import registry from 'k6/x/neofs/registry';
|
|
import { SharedArray } from 'k6/data';
|
|
import { sleep } from 'k6';
|
|
|
|
const obj_list = new SharedArray('obj_list', function () {
|
|
return JSON.parse(open(__ENV.PREGEN_JSON)).objects;
|
|
});
|
|
|
|
const container_list = new SharedArray('container_list', function () {
|
|
return JSON.parse(open(__ENV.PREGEN_JSON)).containers;
|
|
});
|
|
|
|
const read_size = JSON.parse(open(__ENV.PREGEN_JSON)).obj_size;
|
|
|
|
// Select random gRPC endpoint for current VU
|
|
const grpc_endpoints = __ENV.GRPC_ENDPOINTS.split(',');
|
|
const grpc_endpoint = grpc_endpoints[Math.floor(Math.random() * grpc_endpoints.length)];
|
|
const grpc_client = native.connect(grpc_endpoint, '');
|
|
|
|
const registry_enabled = !!__ENV.REGISTRY_FILE;
|
|
const obj_registry = registry_enabled ? registry.open(__ENV.REGISTRY_FILE) : undefined;
|
|
|
|
const duration = __ENV.DURATION;
|
|
|
|
const delete_age = __ENV.DELETE_AGE ? parseInt(__ENV.DELETE_AGE) : undefined;
|
|
let obj_to_delete_selector = undefined;
|
|
if (registry_enabled && delete_age) {
|
|
obj_to_delete_selector = registry.getSelector(
|
|
__ENV.REGISTRY_FILE,
|
|
"obj_to_delete",
|
|
{
|
|
status: "created",
|
|
age: delete_age,
|
|
}
|
|
);
|
|
}
|
|
|
|
|
|
const generator = datagen.generator(1024 * parseInt(__ENV.WRITE_OBJ_SIZE));
|
|
|
|
const scenarios = {};
|
|
|
|
const write_vu_count = parseInt(__ENV.WRITERS || '0');
|
|
if (write_vu_count > 0) {
|
|
scenarios.write = {
|
|
executor: 'constant-vus',
|
|
vus: write_vu_count,
|
|
duration: `${duration}s`,
|
|
exec: 'obj_write',
|
|
gracefulStop: '5s',
|
|
};
|
|
}
|
|
|
|
const read_vu_count = parseInt(__ENV.READERS || '0');
|
|
if (read_vu_count > 0) {
|
|
scenarios.read = {
|
|
executor: 'constant-vus',
|
|
vus: read_vu_count,
|
|
duration: `${duration}s`,
|
|
exec: 'obj_read',
|
|
gracefulStop: '5s',
|
|
};
|
|
}
|
|
|
|
const delete_vu_count = parseInt(__ENV.DELETERS || '0');
|
|
if (delete_vu_count > 0) {
|
|
scenarios.delete = {
|
|
executor: 'constant-vus',
|
|
vus: delete_vu_count,
|
|
duration: `${duration}s`,
|
|
exec: 'obj_delete',
|
|
gracefulStop: '5s',
|
|
};
|
|
}
|
|
|
|
export const options = {
|
|
scenarios,
|
|
setupTimeout: '5s',
|
|
};
|
|
|
|
export function setup() {
|
|
const total_vu_count = write_vu_count + read_vu_count + delete_vu_count;
|
|
|
|
console.log(`Pregenerated containers: ${container_list.length}`);
|
|
console.log(`Pregenerated read object size: ${read_size}`);
|
|
console.log(`Pregenerated total objects: ${obj_list.length}`);
|
|
console.log(`Reading VUs: ${read_vu_count}`);
|
|
console.log(`Writing VUs: ${write_vu_count}`);
|
|
console.log(`Deleting VUs: ${delete_vu_count}`);
|
|
console.log(`Total VUs: ${total_vu_count}`);
|
|
}
|
|
|
|
export function teardown(data) {
|
|
if (obj_registry) {
|
|
obj_registry.close();
|
|
}
|
|
}
|
|
|
|
export function obj_write() {
|
|
if (__ENV.SLEEP) {
|
|
sleep(__ENV.SLEEP);
|
|
}
|
|
|
|
const headers = {
|
|
unique_header: uuidv4()
|
|
};
|
|
const container = container_list[Math.floor(Math.random() * container_list.length)];
|
|
|
|
const { payload, hash } = generator.genPayload(registry_enabled);
|
|
const resp = grpc_client.put(container, headers, payload);
|
|
if (!resp.success) {
|
|
console.log(resp.error);
|
|
return;
|
|
}
|
|
|
|
if (obj_registry) {
|
|
obj_registry.addObject(container, resp.object_id, "", "", hash);
|
|
}
|
|
}
|
|
|
|
export function obj_read() {
|
|
if (__ENV.SLEEP) {
|
|
sleep(__ENV.SLEEP);
|
|
}
|
|
|
|
const obj = obj_list[Math.floor(Math.random() * obj_list.length)];
|
|
const resp = grpc_client.get(obj.container, obj.object)
|
|
if (!resp.success) {
|
|
console.log(resp.error);
|
|
}
|
|
}
|
|
|
|
export function obj_delete() {
|
|
if (__ENV.SLEEP) {
|
|
sleep(__ENV.SLEEP);
|
|
}
|
|
|
|
const obj = obj_to_delete_selector.nextObject();
|
|
if (!obj) {
|
|
// If there are no objects to delete, we reset selector to start scanning from the
|
|
// beginning of registry. Then we wait for some time until suitable object might appear
|
|
obj_to_delete_selector.reset(delete_age);
|
|
sleep(delete_age / 2);
|
|
return;
|
|
}
|
|
|
|
const resp = grpc_client.delete(obj.c_id, obj.o_id);
|
|
if (!resp.success) {
|
|
// Log errors except (2052 - object already deleted)
|
|
console.log(resp.error);
|
|
return;
|
|
}
|
|
|
|
obj_registry.deleteObject(obj.id);
|
|
}
|
|
|
|
export function uuidv4() {
|
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
return v.toString(16);
|
|
});
|
|
}
|