@@ -1424,6 +1424,130 @@ func TestSingleClientLoadingRetry(t *testing.T) {
14241424 })
14251425}
14261426
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+
14271551func BenchmarkSingleClient_DoCache (b * testing.B ) {
14281552 ctx := context .Background ()
14291553 client , err := NewClient (ClientOption {InitAddress : []string {"127.0.0.1:6379" }, Dialer : net.Dialer {KeepAlive : - 1 }})
0 commit comments