@@ -263,6 +263,42 @@ func Test_WatchKey_UpdateStale(t *testing.T) {
263263 })
264264}
265265
266+ func Test_WatchKey_AlwaysRetry (t * testing.T ) {
267+ casBackoffConfig := backoff.Config {
268+ MinBackoff : 1 * time .Millisecond ,
269+ MaxBackoff : 1 * time .Millisecond ,
270+ MaxRetries : 5 , // CAS should retry, but WatchKey should not
271+ }
272+
273+ ddbMock := NewDynamodbClientMock ()
274+ codecMock := & CodecMock {}
275+ c := NewClientMock (ddbMock , codecMock , TestLogger {}, prometheus .NewPedanticRegistry (), defaultPullTime , casBackoffConfig )
276+
277+ // Mock Query to always fail
278+ ddbMock .On ("Query" ).Return (map [string ]dynamodbItem {}, errors .Errorf ("query failed" ))
279+
280+ // WatchKey should not retry on failure (MaxRetries=0), so it should only call Query once
281+ // and then fall back to stale data
282+ staleData := & DescMock {}
283+ staleData .On ("Clone" ).Return (staleData ).Once ()
284+
285+ // Set up some stale data first
286+ c .updateStaleData (key , staleData , time .Now ())
287+
288+ callCount := 0
289+ c .WatchKey (context .TODO (), key , func (i any ) bool {
290+ callCount ++
291+ // Should only be called once with stale data after the first query fails
292+ require .EqualValues (t , staleData , i )
293+ return false // Stop watching
294+ })
295+
296+ // Verify that Query was called exactly 11 times (1 initial + 10 retries due to hardcoded limit in WatchKey)
297+ // This confirms WatchKey has its own retry logic separate from backoff MaxRetries
298+ ddbMock .AssertNumberOfCalls (t , "Query" , 11 )
299+ require .Equal (t , 1 , callCount , "Callback should be called once with stale data" )
300+ }
301+
266302func Test_CAS_UpdateStale (t * testing.T ) {
267303 ddbMock := NewDynamodbClientMock ()
268304 codecMock := & CodecMock {}
0 commit comments