@@ -1345,3 +1345,156 @@ func (t *WorkflowOptionTest) TestKnowQueryType_WithHandlers() {
13451345 },
13461346 wo .KnownQueryTypes ())
13471347}
1348+
1349+ func (s * WorkflowUnitTest ) Test_ResettableTimerFiresAfterExpiration () {
1350+ wf := func (ctx Context ) error {
1351+ timer := NewResettableTimer (ctx , 5 * time .Second )
1352+
1353+ timerFired := false
1354+ NewSelector (ctx ).AddFuture (timer , func (f Future ) {
1355+ err := f .Get (ctx , nil )
1356+ s .NoError (err )
1357+ timerFired = true
1358+ }).Select (ctx )
1359+
1360+ s .True (timerFired , "Timer should fire after 5 seconds with no resets" )
1361+ return nil
1362+ }
1363+
1364+ env := s .NewTestWorkflowEnvironment ()
1365+ env .ExecuteWorkflow (wf )
1366+ s .True (env .IsWorkflowCompleted ())
1367+ s .NoError (env .GetWorkflowError ())
1368+ }
1369+
1370+ func (s * WorkflowUnitTest ) Test_ResettableTimerDoesNotFireWhenKeptReset () {
1371+ wf := func (ctx Context ) error {
1372+ timer := NewResettableTimer (ctx , 2 * time .Second )
1373+ activityCh := GetSignalChannel (ctx , "activity" )
1374+ stopCh := GetSignalChannel (ctx , "stop" )
1375+
1376+ timerFired := false
1377+ activityCount := 0
1378+ stopped := false
1379+
1380+ for ! stopped {
1381+ selector := NewSelector (ctx )
1382+
1383+ selector .AddFuture (timer , func (f Future ) {
1384+ timerFired = true
1385+ })
1386+
1387+ selector .AddReceive (activityCh , func (c Channel , more bool ) {
1388+ var signal string
1389+ c .Receive (ctx , & signal )
1390+ activityCount ++
1391+ timer .Reset ()
1392+ })
1393+
1394+ selector .AddReceive (stopCh , func (c Channel , more bool ) {
1395+ var stop bool
1396+ c .Receive (ctx , & stop )
1397+ stopped = true
1398+ })
1399+
1400+ selector .Select (ctx )
1401+ }
1402+
1403+ s .Equal (3 , activityCount , "Should have received 3 activity signals" )
1404+ s .False (timerFired , "Timer should NOT fire when continuously reset" )
1405+ return nil
1406+ }
1407+
1408+ env := s .NewTestWorkflowEnvironment ()
1409+
1410+ env .RegisterDelayedCallback (func () {
1411+ env .SignalWorkflow ("activity" , "scan1" )
1412+ }, 500 * time .Millisecond )
1413+ env .RegisterDelayedCallback (func () {
1414+ env .SignalWorkflow ("activity" , "scan2" )
1415+ }, 1500 * time .Millisecond )
1416+ env .RegisterDelayedCallback (func () {
1417+ env .SignalWorkflow ("activity" , "scan3" )
1418+ }, 2500 * time .Millisecond )
1419+ env .RegisterDelayedCallback (func () {
1420+ env .SignalWorkflow ("stop" , true )
1421+ }, 4 * time .Second )
1422+
1423+ env .ExecuteWorkflow (wf )
1424+ s .True (env .IsWorkflowCompleted ())
1425+ s .NoError (env .GetWorkflowError ())
1426+ }
1427+
1428+ func (s * WorkflowUnitTest ) Test_ResettableTimerFiresAfterResetsStop () {
1429+ wf := func (ctx Context ) error {
1430+ timer := NewResettableTimer (ctx , 5 * time .Second )
1431+
1432+ timer .Reset () // Still 5s
1433+ timer .Reset (2 * time .Second ) // Now 2s
1434+
1435+ timerFired := false
1436+ NewSelector (ctx ).AddFuture (timer , func (f Future ) {
1437+ err := f .Get (ctx , nil )
1438+ s .NoError (err )
1439+ timerFired = true
1440+ }).Select (ctx )
1441+
1442+ s .True (timerFired , "Timer should eventually fire after resets stop" )
1443+ return nil
1444+ }
1445+
1446+ env := s .NewTestWorkflowEnvironment ()
1447+ env .ExecuteWorkflow (wf )
1448+ s .True (env .IsWorkflowCompleted ())
1449+ s .NoError (env .GetWorkflowError ())
1450+ }
1451+
1452+ func (s * WorkflowUnitTest ) Test_ResettableTimerResetAfterFireIsNoop () {
1453+ wf := func (ctx Context ) error {
1454+ timer := NewResettableTimer (ctx , 1 * time .Second )
1455+
1456+ err := timer .Get (ctx , nil )
1457+ s .NoError (err )
1458+ s .True (timer .IsReady (), "Timer should be ready after firing" )
1459+
1460+ timer .Reset (5 * time .Second )
1461+ s .True (timer .IsReady (), "Timer should still be ready (reset was no-op)" )
1462+
1463+ timer .Reset ()
1464+ s .True (timer .IsReady (), "Multiple resets after fire are all no-ops" )
1465+ return nil
1466+ }
1467+
1468+ env := s .NewTestWorkflowEnvironment ()
1469+ env .ExecuteWorkflow (wf )
1470+ s .True (env .IsWorkflowCompleted ())
1471+ s .NoError (env .GetWorkflowError ())
1472+ }
1473+
1474+ func (s * WorkflowUnitTest ) Test_ResettableTimerResetWithDifferentDurations () {
1475+ wf := func (ctx Context ) error {
1476+ timer := NewResettableTimer (ctx , 10 * time .Second )
1477+
1478+ timer .Reset (1 * time .Second )
1479+
1480+ timerFired := false
1481+ startTime := Now (ctx )
1482+
1483+ NewSelector (ctx ).AddFuture (timer , func (f Future ) {
1484+ err := f .Get (ctx , nil )
1485+ s .NoError (err )
1486+ timerFired = true
1487+ }).Select (ctx )
1488+
1489+ elapsed := Now (ctx ).Sub (startTime )
1490+
1491+ s .True (timerFired , "Timer should fire" )
1492+ s .Less (elapsed , 5 * time .Second , "Should fire with reset duration, not original" )
1493+ return nil
1494+ }
1495+
1496+ env := s .NewTestWorkflowEnvironment ()
1497+ env .ExecuteWorkflow (wf )
1498+ s .True (env .IsWorkflowCompleted ())
1499+ s .NoError (env .GetWorkflowError ())
1500+ }
0 commit comments