Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix (Core) Fixed calculateBackoffTime in JobQueueManagerAPIImpl #30350

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ public class JobQueueManagerAPIImpl implements JobQueueManagerAPI {
private final EventProducer eventProducer;
private final JobProcessorFactory jobProcessorFactory;

// Cap to prevent overflow
private static final int MAX_EMPTY_QUEUE_COUNT = 30;
// Arbitrary threshold to reset
private static final int EMPTY_QUEUE_RESET_THRESHOLD = Integer.MAX_VALUE - 1000;

/**
* Constructs a new JobQueueManagerAPIImpl.
* This constructor initializes the job queue manager with all necessary dependencies and configurations.
Expand Down Expand Up @@ -473,9 +478,11 @@ private void processJobs() {
} else {
// If no jobs were found, wait for a short time before checking again
// Implement exponential backoff when queue is repeatedly empty
long sleepTime = Math.min(1000 * (long) Math.pow(2, emptyQueueCount), 30000);
long sleepTime = calculateBackoffTime(emptyQueueCount, MAX_EMPTY_QUEUE_COUNT);
Thread.sleep(sleepTime);
emptyQueueCount++;
emptyQueueCount = incrementAndResetEmptyQueueCount(
emptyQueueCount, MAX_EMPTY_QUEUE_COUNT, EMPTY_QUEUE_RESET_THRESHOLD
);
}
} catch (InterruptedException e) {
Logger.error(this, "Job processing thread interrupted: " + e.getMessage(), e);
Expand Down Expand Up @@ -965,6 +972,37 @@ private float getJobProgress(final Job job) {
return progress;
}

/**
* Calculates the backoff time based on the number of empty queue counts.
*
* @param emptyQueueCount the current count of empty queue checks
* @param maxEmptyQueueCount the maximum count of empty queue checks
* @return the calculated backoff time in milliseconds, the result is capped at 30,000
* milliseconds (30 seconds) to prevent excessively long sleep times.
*/
@VisibleForTesting
public long calculateBackoffTime(int emptyQueueCount, int maxEmptyQueueCount) {
emptyQueueCount = Math.min(emptyQueueCount, maxEmptyQueueCount);
return Math.min(1000L * (1L << emptyQueueCount), 30000L);
}

/**
* Increments the empty queue count and resets it if it exceeds the reset threshold.
*
* @param emptyQueueCount the current count of empty queue checks
* @param maxEmptyQueueCount the maximum count of empty queue checks
* @param resetThreshold the threshold at which the empty queue count should be reset
* @return the updated empty queue count
*/
private int incrementAndResetEmptyQueueCount(
int emptyQueueCount, int maxEmptyQueueCount, int resetThreshold) {
emptyQueueCount++;
if (emptyQueueCount > resetThreshold) {
emptyQueueCount = maxEmptyQueueCount; // Reset to max to avoid wrap around
}
return emptyQueueCount;
}

/**
* A wrapper class that makes ScheduledExecutorService auto-closeable. This class is designed to
* be used with try-with-resources to ensure that the ScheduledExecutorService is properly shut
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1290,6 +1290,26 @@ public void test_complex_cancelJob() throws Exception {
jobQueueManagerAPI.close();
}

/**
* Method to test: calculateBackoffTime in JobQueueManagerAPI
* Given Scenario: Various empty queue counts and maximum empty queue count
* ExpectedResult: Correct backoff times are calculated
*/
@Test
public void test_calculateBackoffTime() {

JobQueueManagerAPIImpl jobQueueManager = (JobQueueManagerAPIImpl) jobQueueManagerAPI;

assertEquals(1000L, jobQueueManager.calculateBackoffTime(0, 30));
assertEquals(2000L, jobQueueManager.calculateBackoffTime(1, 30));
assertEquals(4000L, jobQueueManager.calculateBackoffTime(2, 30));
assertEquals(8000L, jobQueueManager.calculateBackoffTime(3, 30));
assertEquals(16000L, jobQueueManager.calculateBackoffTime(4, 30));
assertEquals(30000L, jobQueueManager.calculateBackoffTime(5, 30));
assertEquals(30000L, jobQueueManager.calculateBackoffTime(6, 30));
assertEquals(30000L, jobQueueManager.calculateBackoffTime(30, 30));
}

/**
* Creates a new instance of the JobQueueManagerAPI with the provided configurations.
*
Expand Down