Scenario
I am creating some records in a system using three requests of its API. In the first request I need to send and Id which for testing and tracking purposes I am using a consecutive number generated in a sampler.
I need to test how the system behaves under high loads, so I started with 16 threads per second and set the loop to 3000 to run it for about 50 minutes to monitor behavior.
I expected to run for about 50 minutes and create 48000 records.
What happened?
Once I ran it, I started watching some errors in the first request, related to IDs being duplicated. Some requests were rejected because the Id already exists. This is correct behavior, but I did not expect to be generating duplicated Ids.
How is it done? THe overall structure is this. Please consider the grayed-out items are disabled.
The SetUp Thread Group has a Sampler to initialize the counter of IDs. I use a file to store the last used Id, and this sampler verifies the file exists or not and creates it accordingly with an initial value.
All sampler codes are Java, BeanShell 2.0b6 and BeanShell Engine 1.0.
import java.io.*;
import java.util.concurrent.locks.ReentrantLock;
// Define the file path for the counter
File counterFile = new File("/Users/rickersilva/Documents/Zenus2Testing/prelive-counter.txt");
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// Check if the counter file exists
if (!counterFile.exists()) {
// If not, create it and set the initial value
BufferedWriter writer = new BufferedWriter(new FileWriter(counterFile));
writer.write("90000000"); // Initial value
writer.close();
log.info("DEV_LOG: Counter initialized with value 90000000");
} else {
log.info("DEV_LOG: Counter file already exists, skipping initialization.");
}
} catch (IOException e) {
log.error("DEV_LOG: Error initializing counter: " + e);
} finally {
lock.unlock();
}
Having set that up, I set some user defined variables not related to this case, headers and so on. In the Create Person request I have the DNI increment preprocessor. Its purpose is to provide a safe way to acces the file, read the ID, increment it and save it back to the file. I use a lock to prevent the threads to open it at the same time, expecting not to use the same Id in create person requests. This is clearly not working, and here is the code.
import java.io.*;
import java.util.concurrent.locks.ReentrantLock;
ReentrantLock lock = new ReentrantLock();
File counterFile = new File("/Users/rickersilva/Documents/Zenus2Testing/prelive-counter.txt");
int currentDni;
int nextDni;
String idNumber;
lock.lock();
try {
// Read the current value of personDni from the file
BufferedReader reader = new BufferedReader(new FileReader(counterFile));
currentDni = Integer.parseInt(reader.readLine().trim());
reader.close();
// Increment the personDni and update the file
nextDni = currentDni + 1;
BufferedWriter writer = new BufferedWriter(new FileWriter(counterFile, false));
writer.write(Integer.toString(nextDni));
writer.close();
// Set the personDni variable in JMeter
idNumber = "16" + Integer.toString(nextDni);
vars.put("idNumber", idNumber);
} catch (Exception e) {
log.error("DEV_LOG: Error processing personDni: " + e);
} finally {
lock.unlock();
}
The extractor catches the personId returned by the API to be used in the next requests.
I cannot see why this could be failing. Highly possible my understanding of locking is not good in this scenario. But I cannot figure out other way to accomplish this. I appreciate your time and help.



