@@ -1575,3 +1575,127 @@ func (s *contextTestSuite) TestAllocateTimerIDsLocked_WhenMultipleTasksProvidedA
1575
1575
s .True (task1 .GetTaskID () > 0 , "Task 1 ID should be positive" )
1576
1576
s .True (task2 .GetTaskID () > 0 , "Task 2 ID should be positive" )
1577
1577
}
1578
+
1579
+ func (s * contextTestSuite ) TestAllocateTimerIDsLocked () {
1580
+ s .mockResource .TimeSource = clock .NewMockedTimeSourceAt (time .Now ())
1581
+ testTimeNow := s .mockResource .TimeSource .Now ()
1582
+ testVisibilityTime := testTimeNow .Add (- time .Hour ).Truncate (persistence .DBTimestampMinPrecision )
1583
+ testReadCursorTime := testTimeNow .Add (time .Minute ).Truncate (persistence .DBTimestampMinPrecision )
1584
+ testFutureTime := testTimeNow .Add (30 * time .Minute ).Truncate (persistence .DBTimestampMinPrecision )
1585
+
1586
+ domainInfo := & persistence.DomainInfo {
1587
+ ID : testDomainID ,
1588
+ Name : testDomain ,
1589
+ }
1590
+
1591
+ tests := []struct {
1592
+ name string
1593
+ setupContext func (* contextImpl )
1594
+ setupMocks func ()
1595
+ domainEntry * cache.DomainCacheEntry
1596
+ workflowID string
1597
+ timerTasks []persistence.Task
1598
+ expectError bool
1599
+ expectedErrorMsg string
1600
+ validateResults func (* testing.T , * contextImpl , []persistence.Task )
1601
+ }{
1602
+ {
1603
+ name : "Queue V2 enabled - simple case" ,
1604
+ setupContext : func (ctx * contextImpl ) {
1605
+ ctx .config .EnableTimerQueueV2 = func (shardID int ) bool { return true }
1606
+ ctx .scheduledTaskMaxReadLevelMap [cluster .TestCurrentClusterName ] = testReadCursorTime
1607
+ },
1608
+ domainEntry : cache .NewLocalDomainCacheEntryForTest (domainInfo , & persistence.DomainConfig {}, cluster .TestCurrentClusterName ),
1609
+ workflowID : testWorkflowID ,
1610
+ timerTasks : []persistence.Task {
1611
+ & persistence.UserTimerTask {
1612
+ TaskData : persistence.TaskData {
1613
+ VisibilityTimestamp : testFutureTime ,
1614
+ },
1615
+ },
1616
+ },
1617
+ expectError : false ,
1618
+ validateResults : func (t * testing.T , ctx * contextImpl , tasks []persistence.Task ) {
1619
+ require .Len (t , tasks , 1 )
1620
+ // Task should keep its future timestamp
1621
+ assert .Equal (t , testFutureTime , tasks [0 ].GetVisibilityTimestamp ())
1622
+ },
1623
+ },
1624
+ {
1625
+ name : "Task timestamp before read cursor - should adjust timestamp" ,
1626
+ setupContext : func (ctx * contextImpl ) {
1627
+ ctx .config .EnableTimerQueueV2 = func (shardID int ) bool { return true }
1628
+ ctx .scheduledTaskMaxReadLevelMap [cluster .TestCurrentClusterName ] = testReadCursorTime
1629
+ ctx .logger = testlogger .New (s .T ())
1630
+ },
1631
+ domainEntry : cache .NewLocalDomainCacheEntryForTest (domainInfo , & persistence.DomainConfig {}, cluster .TestCurrentClusterName ),
1632
+ workflowID : testWorkflowID ,
1633
+ timerTasks : []persistence.Task {
1634
+ & persistence.UserTimerTask {
1635
+ TaskData : persistence.TaskData {
1636
+ VisibilityTimestamp : testVisibilityTime ,
1637
+ },
1638
+ },
1639
+ },
1640
+ expectError : false ,
1641
+ validateResults : func (t * testing.T , ctx * contextImpl , tasks []persistence.Task ) {
1642
+ require .Len (t , tasks , 1 )
1643
+ // Timestamp should have been adjusted to read cursor + precision
1644
+ expectedTime := testReadCursorTime .Add (persistence .DBTimestampMinPrecision )
1645
+ assert .Equal (t , expectedTime , tasks [0 ].GetVisibilityTimestamp ())
1646
+ },
1647
+ },
1648
+ {
1649
+ name : "Task timestamp before current time - should use current time as base" ,
1650
+ setupContext : func (ctx * contextImpl ) {
1651
+ ctx .config .EnableTimerQueueV2 = func (shardID int ) bool { return true }
1652
+ // Set read cursor to past time
1653
+ ctx .scheduledTaskMaxReadLevelMap [cluster .TestCurrentClusterName ] = testTimeNow .Add (- 2 * time .Hour )
1654
+ },
1655
+ domainEntry : cache .NewLocalDomainCacheEntryForTest (domainInfo , & persistence.DomainConfig {}, cluster .TestCurrentClusterName ),
1656
+ workflowID : testWorkflowID ,
1657
+ timerTasks : []persistence.Task {
1658
+ & persistence.UserTimerTask {
1659
+ TaskData : persistence.TaskData {
1660
+ VisibilityTimestamp : testVisibilityTime ,
1661
+ },
1662
+ },
1663
+ },
1664
+ expectError : false ,
1665
+ validateResults : func (t * testing.T , ctx * contextImpl , tasks []persistence.Task ) {
1666
+ require .Len (t , tasks , 1 )
1667
+ // Should use current time as base for adjustment
1668
+ expectedTime := testTimeNow .Truncate (persistence .DBTimestampMinPrecision ).Add (persistence .DBTimestampMinPrecision )
1669
+ assert .Equal (t , expectedTime , tasks [0 ].GetVisibilityTimestamp ())
1670
+ },
1671
+ },
1672
+ }
1673
+
1674
+ for _ , tt := range tests {
1675
+ s .Run (tt .name , func () {
1676
+ // Reset context to clean state
1677
+ context := s .newContext ()
1678
+
1679
+ // Apply test-specific setup
1680
+ if tt .setupContext != nil {
1681
+ tt .setupContext (context )
1682
+ }
1683
+
1684
+ // Execute the method under test
1685
+ err := context .allocateTimerIDsLocked (tt .domainEntry , tt .workflowID , tt .timerTasks )
1686
+
1687
+ // Validate results
1688
+ if tt .expectError {
1689
+ s .Error (err )
1690
+ if tt .expectedErrorMsg != "" {
1691
+ s .Contains (err .Error (), tt .expectedErrorMsg )
1692
+ }
1693
+ } else {
1694
+ s .NoError (err )
1695
+ if tt .validateResults != nil {
1696
+ tt .validateResults (s .T (), context , tt .timerTasks )
1697
+ }
1698
+ }
1699
+ })
1700
+ }
1701
+ }
0 commit comments