@@ -1424,6 +1424,130 @@ func TestSingleClientLoadingRetry(t *testing.T) {
1424
1424
})
1425
1425
}
1426
1426
1427
+ func TestSingleClientConnLifetime (t * testing.T ) {
1428
+ defer ShouldNotLeaked (SetupLeakDetection ())
1429
+
1430
+ setup := func () (* singleClient , * mockConn ) {
1431
+ m := & mockConn {}
1432
+ client , err := newSingleClient (
1433
+ & ClientOption {InitAddress : []string {"" }, ConnLifetime : 5 * time .Second },
1434
+ m ,
1435
+ func (dst string , opt * ClientOption ) conn { return m },
1436
+ newRetryer (defaultRetryDelayFn ),
1437
+ )
1438
+ if err != nil {
1439
+ t .Fatalf ("unexpected err %v" , err )
1440
+ }
1441
+ return client , m
1442
+ }
1443
+
1444
+ t .Run ("Do" , func (t * testing.T ) {
1445
+ client , m := setup ()
1446
+ m .DoFn = func (cmd Completed ) RedisResult {
1447
+ return newResult (strmsg ('+' , "OK" ), nil )
1448
+ }
1449
+ if v , err := client .Do (context .Background (), client .B ().Get ().Key ("Do" ).Build ()).ToString (); err != nil || v != "OK" {
1450
+ t .Fatalf ("unexpected response %v %v" , v , err )
1451
+ }
1452
+ })
1453
+
1454
+ t .Run ("DoMulti" , func (t * testing.T ) {
1455
+ client , m := setup ()
1456
+ m .DoMultiFn = func (multi ... Completed ) * redisresults {
1457
+ return & redisresults {s : []RedisResult {newResult (strmsg ('+' , "OK" ), nil )}}
1458
+ }
1459
+ if v , err := client .DoMulti (context .Background (), client .B ().Get ().Key ("Do" ).Build ())[0 ].ToString (); err != nil || v != "OK" {
1460
+ t .Fatalf ("unexpected response %v %v" , v , err )
1461
+ }
1462
+ })
1463
+
1464
+ t .Run ("DoMulti ConnLifetime - at the head of processing" , func (t * testing.T ) {
1465
+ client , m := setup ()
1466
+ attempts := 0
1467
+ m .DoMultiFn = func (multi ... Completed ) * redisresults {
1468
+ attempts ++
1469
+ if attempts == 1 {
1470
+ return & redisresults {s : []RedisResult {newErrResult (errConnExpired )}}
1471
+ }
1472
+ return & redisresults {s : []RedisResult {newResult (strmsg ('+' , "OK" ), nil )}}
1473
+ }
1474
+ if v , err := client .DoMulti (context .Background (), client .B ().Get ().Key ("Do" ).Build ())[0 ].ToString (); err != nil || v != "OK" {
1475
+ t .Fatalf ("unexpected response %v %v" , v , err )
1476
+ }
1477
+ })
1478
+
1479
+ t .Run ("DoMulti ConnLifetime in the middle of processing" , func (t * testing.T ) {
1480
+ client , m := setup ()
1481
+ attempts := 0
1482
+ m .DoMultiFn = func (multi ... Completed ) * redisresults {
1483
+ attempts ++
1484
+ if attempts == 1 {
1485
+ return & redisresults {s : []RedisResult {newResult (strmsg ('+' , "OK" ), nil ), newErrResult (errConnExpired )}}
1486
+ }
1487
+ // recover the failure of the first call
1488
+ return & redisresults {s : []RedisResult {newResult (strmsg ('+' , "OK" ), nil )}}
1489
+ }
1490
+ resps := client .DoMulti (context .Background (), client .B ().Get ().Key ("Do" ).Build (), client .B ().Get ().Key ("Do" ).Build ())
1491
+ if len (resps ) != 2 {
1492
+ t .Errorf ("unexpected response length %v" , len (resps ))
1493
+ }
1494
+ for _ , resp := range resps {
1495
+ if v , err := resp .ToString (); err != nil || v != "OK" {
1496
+ t .Fatalf ("unexpected response %v %v" , v , err )
1497
+ }
1498
+ }
1499
+ })
1500
+
1501
+ t .Run ("DoMultiCache" , func (t * testing.T ) {
1502
+ client , m := setup ()
1503
+ m .DoMultiCacheFn = func (multi ... CacheableTTL ) * redisresults {
1504
+ return & redisresults {s : []RedisResult {newResult (strmsg ('+' , "OK" ), nil )}}
1505
+ }
1506
+ cmd := client .B ().Get ().Key ("Do" ).Cache ()
1507
+ if v , err := client .DoMultiCache (context .Background (), CT (cmd , 0 ))[0 ].ToString (); err != nil || v != "OK" {
1508
+ t .Fatalf ("unexpected response %v %v" , v , err )
1509
+ }
1510
+ })
1511
+
1512
+ t .Run ("DoMultiCache ConnLifetime - at the head of processing" , func (t * testing.T ) {
1513
+ client , m := setup ()
1514
+ attempts := 0
1515
+ m .DoMultiCacheFn = func (multi ... CacheableTTL ) * redisresults {
1516
+ attempts ++
1517
+ if attempts == 1 {
1518
+ return & redisresults {s : []RedisResult {newErrResult (errConnExpired )}}
1519
+ }
1520
+ return & redisresults {s : []RedisResult {newResult (strmsg ('+' , "OK" ), nil )}}
1521
+ }
1522
+ cmd := client .B ().Get ().Key ("Do" ).Cache ()
1523
+ if v , err := client .DoMultiCache (context .Background (), CT (cmd , 0 ))[0 ].ToString (); err != nil || v != "OK" {
1524
+ t .Fatalf ("unexpected response %v %v" , v , err )
1525
+ }
1526
+ })
1527
+
1528
+ t .Run ("DoMultiCache ConnLifetime in the middle of processing" , func (t * testing.T ) {
1529
+ client , m := setup ()
1530
+ attempts := 0
1531
+ m .DoMultiCacheFn = func (multi ... CacheableTTL ) * redisresults {
1532
+ attempts ++
1533
+ if attempts == 1 {
1534
+ return & redisresults {s : []RedisResult {newResult (strmsg ('+' , "OK" ), nil ), newErrResult (errConnExpired )}}
1535
+ }
1536
+ // recover the failure of the first call
1537
+ return & redisresults {s : []RedisResult {newResult (strmsg ('+' , "OK" ), nil )}}
1538
+ }
1539
+ resps := client .DoMultiCache (context .Background (), CT (client .B ().Get ().Key ("Do" ).Cache (), 0 ), CT (client .B ().Get ().Key ("Do" ).Cache (), 0 ))
1540
+ if len (resps ) != 2 {
1541
+ t .Errorf ("unexpected response length %v" , len (resps ))
1542
+ }
1543
+ for _ , resp := range resps {
1544
+ if v , err := resp .ToString (); err != nil || v != "OK" {
1545
+ t .Fatalf ("unexpected response %v %v" , v , err )
1546
+ }
1547
+ }
1548
+ })
1549
+ }
1550
+
1427
1551
func BenchmarkSingleClient_DoCache (b * testing.B ) {
1428
1552
ctx := context .Background ()
1429
1553
client , err := NewClient (ClientOption {InitAddress : []string {"127.0.0.1:6379" }, Dialer : net.Dialer {KeepAlive : - 1 }})
0 commit comments