Skip to content

Commit f499659

Browse files
committed
chore: Nextdelay must be greater than 0
Signed-off-by: Javier Aliaga <javier@diagrid.io>
1 parent e4c3cb3 commit f499659

3 files changed

Lines changed: 38 additions & 16 deletions

File tree

durabletask-client/src/main/java/io/dapr/durabletask/RetryPolicy.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
package io.dapr.durabletask;
1515

1616
import javax.annotation.Nullable;
17+
1718
import java.time.Duration;
18-
import java.util.Objects;
19+
import java.util.Random;
1920

2021
/**
2122
* A declarative retry policy that can be configured for activity or sub-orchestration calls.
@@ -206,4 +207,22 @@ public RetryPolicy setJitterFactor(double jitterFactor) {
206207
public double getJitterFactor() {
207208
return this.jitterFactor;
208209
}
210+
211+
/**
212+
* Applies jitter to a delay value, reducing it by a deterministic random fraction
213+
* in [0, jitterFactor). The result is guaranteed to be at least 1ms.
214+
*
215+
* @param delayInMillis the base delay in milliseconds (must be positive)
216+
* @param jitterFactor the jitter factor in [0.0, 1.0]
217+
* @param seed deterministic seed for the random number generator
218+
* @return the jittered delay in milliseconds, always >= 1
219+
*/
220+
static long applyJitter(long delayInMillis, double jitterFactor, long seed) {
221+
if (jitterFactor > 0.0) {
222+
double reduction = new Random(seed).nextDouble() * jitterFactor;
223+
delayInMillis = (long) (delayInMillis * (1.0 - reduction));
224+
return Math.max(delayInMillis, 1);
225+
}
226+
return delayInMillis;
227+
}
209228
}

durabletask-client/src/main/java/io/dapr/durabletask/TaskOrchestrationExecutor.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import java.util.List;
3939
import java.util.Map;
4040
import java.util.Queue;
41-
import java.util.Random;
4241
import java.util.Set;
4342
import java.util.UUID;
4443
import java.util.concurrent.CancellationException;
@@ -1520,12 +1519,9 @@ private Duration getNextDelay() {
15201519
// Apply jitter: reduce delay by a random fraction in [0, jitterFactor).
15211520
// Seed is deterministic so that replay computes the same finalFireAt, preventing
15221521
// the createTimerChain callback from creating spurious extra sub-timers.
1523-
double jitterFactor = this.policy.getJitterFactor();
1524-
if (jitterFactor > 0.0) {
1525-
long seed = this.firstAttempt.toEpochMilli() + this.attemptNumber;
1526-
double reduction = new Random(seed).nextDouble() * jitterFactor;
1527-
nextDelayInMillis = (long) (nextDelayInMillis * (1.0 - reduction));
1528-
}
1522+
long seed = this.firstAttempt.toEpochMilli() + this.attemptNumber;
1523+
nextDelayInMillis = RetryPolicy.applyJitter(
1524+
nextDelayInMillis, this.policy.getJitterFactor(), seed);
15291525

15301526
return Duration.ofMillis(nextDelayInMillis);
15311527
}

durabletask-client/src/test/java/io/dapr/durabletask/RetryPolicyTest.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import org.junit.jupiter.api.Test;
1717

1818
import java.time.Duration;
19-
import java.util.Random;
2019

2120
import static org.junit.jupiter.api.Assertions.*;
2221

@@ -82,18 +81,26 @@ void jitterFactorPositiveInfinityThrows() {
8281

8382

8483
/**
85-
8684
* With jitterFactor=0 the delay must be unchanged.
8785
*/
8886
@Test
8987
void zeroJitterLeavesDelayUnchanged() {
9088
long baseDelayMillis = 3000L;
91-
double jitterFactor = 0.0;
92-
93-
long seed = 42L;
94-
double reduction = new Random(seed).nextDouble() * jitterFactor;
95-
long reduced = (long) (baseDelayMillis * (1.0 - reduction));
89+
assertEquals(baseDelayMillis, RetryPolicy.applyJitter(baseDelayMillis, 0.0, 42L));
90+
}
9691

97-
assertEquals(baseDelayMillis, reduced);
92+
/**
93+
* With jitterFactor=1.0 the delay must never drop below 1ms,
94+
* even when nextDouble() approaches 1.0.
95+
*/
96+
@Test
97+
void jitterWithMaxFactorNeverProducesZeroDelay() {
98+
long baseDelayMillis = 1L; // smallest meaningful delay
99+
100+
for (int seed = 0; seed < 1000; seed++) {
101+
long result = RetryPolicy.applyJitter(baseDelayMillis, 1.0, seed);
102+
assertTrue(result >= 1,
103+
"Delay must be at least 1ms, but was " + result + " for seed " + seed);
104+
}
98105
}
99106
}

0 commit comments

Comments
 (0)