@@ -87,8 +87,14 @@ void emptyOrchestration() throws TimeoutException {
87
87
void singleTimer () throws IOException , TimeoutException {
88
88
final String orchestratorName = "SingleTimer" ;
89
89
final Duration delay = Duration .ofSeconds (3 );
90
+ AtomicReferenceArray <LocalDateTime > timestamps = new AtomicReferenceArray <>(2 );
91
+ AtomicInteger counter = new AtomicInteger ();
90
92
DurableTaskGrpcWorker worker = this .createWorkerBuilder ()
91
- .addOrchestrator (orchestratorName , ctx -> ctx .createTimer (delay ).await ())
93
+ .addOrchestrator (orchestratorName , ctx -> {
94
+ timestamps .set (counter .get (), LocalDateTime .now ());
95
+ counter .incrementAndGet ();
96
+ ctx .createTimer (delay ).await ();
97
+ })
92
98
.buildAndStart ();
93
99
94
100
DurableTaskClient client = new DurableTaskGrpcClientBuilder ().build ();
@@ -103,11 +109,22 @@ void singleTimer() throws IOException, TimeoutException {
103
109
long expectedCompletionSecond = instance .getCreatedAt ().plus (delay ).getEpochSecond ();
104
110
long actualCompletionSecond = instance .getLastUpdatedAt ().getEpochSecond ();
105
111
assertTrue (expectedCompletionSecond <= actualCompletionSecond );
112
+
113
+ // Verify that the correct number of timers were created
114
+ // This should yield 2 (first invocation + replay invocations for internal timers)
115
+ assertEquals (2 , counter .get ());
116
+
117
+ // Verify that each timer is the expected length
118
+ int [] secondsElapsed = new int [1 ];
119
+ for (int i = 0 ; i < timestamps .length () - 1 ; i ++) {
120
+ secondsElapsed [i ] = timestamps .get (i + 1 ).getSecond () - timestamps .get (i ).getSecond ();
121
+ }
122
+ assertEquals (secondsElapsed [0 ], 3 );
123
+
106
124
}
107
125
}
108
126
109
127
@ Test
110
- @ Disabled ("Test is disabled for investigation, fixing the test retry pattern exposed the failure (could be timer creation issue)" )
111
128
void longTimer () throws TimeoutException {
112
129
final String orchestratorName = "LongTimer" ;
113
130
final Duration delay = Duration .ofSeconds (7 );
@@ -285,6 +302,31 @@ void singleTimeStampTimer() throws IOException, TimeoutException {
285
302
}
286
303
}
287
304
305
+
306
+ @ Test
307
+ void singleTimeStampCreateTimer () throws IOException , TimeoutException {
308
+ final String orchestratorName = "SingleTimeStampTimer" ;
309
+ final Duration delay = Duration .ofSeconds (3 );
310
+ final ZonedDateTime zonedDateTime = ZonedDateTime .of (LocalDateTime .now ().plusSeconds (delay .getSeconds ()), ZoneId .systemDefault ());
311
+ DurableTaskGrpcWorker worker = this .createWorkerBuilder ()
312
+ .addOrchestrator (orchestratorName , ctx -> ctx .createTimer (zonedDateTime ).await ())
313
+ .buildAndStart ();
314
+
315
+ DurableTaskClient client = new DurableTaskGrpcClientBuilder ().build ();
316
+ try (worker ; client ) {
317
+ String instanceId = client .scheduleNewOrchestrationInstance (orchestratorName );
318
+ Duration timeout = delay .plus (defaultTimeout );
319
+ OrchestrationMetadata instance = client .waitForInstanceCompletion (instanceId , timeout , false );
320
+ assertNotNull (instance );
321
+ assertEquals (OrchestrationRuntimeStatus .COMPLETED , instance .getRuntimeStatus ());
322
+
323
+ // Verify that the delay actually happened
324
+ long expectedCompletionSecond = zonedDateTime .toInstant ().getEpochSecond ();
325
+ long actualCompletionSecond = instance .getLastUpdatedAt ().getEpochSecond ();
326
+ assertTrue (expectedCompletionSecond <= actualCompletionSecond );
327
+ }
328
+ }
329
+
288
330
@ Test
289
331
void isReplaying () throws IOException , InterruptedException , TimeoutException {
290
332
final String orchestratorName = "SingleTimer" ;
0 commit comments