@@ -1526,102 +1526,79 @@ func (c *ClusterClient) processTxPipeline(ctx context.Context, cmds []Cmder) err
1526
1526
return err
1527
1527
}
1528
1528
1529
- cmdsMap := map [ int ][] Cmder {}
1529
+ keyedCmdsBySlot := c . slottedKeyedCommands ( cmds )
1530
1530
slot := - 1
1531
- // get only the keyed commands
1532
- keyedCmds := c .keyedCmds (cmds )
1533
- if len (keyedCmds ) == 0 {
1534
- // no keyed commands try random slot
1531
+ switch len (keyedCmdsBySlot ) {
1532
+ case 0 :
1535
1533
slot = hashtag .RandomSlot ()
1536
- } else {
1537
- // keyed commands, get slot from them
1538
- // if more than one slot, return cross slot error
1539
- cmdsBySlot := c .mapCmdsBySlot (keyedCmds )
1540
- if len (cmdsBySlot ) > 1 {
1541
- // cross slot error, we have more than one slot for keyed commands
1542
- setCmdsErr (cmds , ErrCrossSlot )
1543
- return ErrCrossSlot
1544
- }
1545
- // get the slot, should be only one
1546
- for sl := range cmdsBySlot {
1534
+ case 1 :
1535
+ for sl := range keyedCmdsBySlot {
1547
1536
slot = sl
1548
1537
break
1549
1538
}
1550
- }
1551
- // slot was not determined, try random one
1552
- if slot == - 1 {
1553
- slot = hashtag .RandomSlot ()
1554
- }
1555
- cmdsMap [slot ] = cmds
1556
-
1557
- // TxPipeline does not support cross slot transaction.
1558
- // double check the commands are in the same slot
1559
- if len (cmdsMap ) > 1 {
1539
+ default :
1540
+ // TxPipeline does not support cross slot transaction.
1560
1541
setCmdsErr (cmds , ErrCrossSlot )
1561
1542
return ErrCrossSlot
1562
1543
}
1563
1544
1564
- for slot , cmds := range cmdsMap {
1565
- node , err := state .slotMasterNode (slot )
1566
- if err != nil {
1567
- setCmdsErr (cmds , err )
1568
- continue
1569
- }
1545
+ node , err := state .slotMasterNode (slot )
1546
+ if err != nil {
1547
+ setCmdsErr (cmds , err )
1548
+ return err
1549
+ }
1570
1550
1571
- cmdsMap := map [* clusterNode ][]Cmder {node : cmds }
1572
- for attempt := 0 ; attempt <= c .opt .MaxRedirects ; attempt ++ {
1573
- if attempt > 0 {
1574
- if err := internal .Sleep (ctx , c .retryBackoff (attempt )); err != nil {
1575
- setCmdsErr (cmds , err )
1576
- return err
1577
- }
1551
+ cmdsMap := map [* clusterNode ][]Cmder {node : cmds }
1552
+ for attempt := 0 ; attempt <= c .opt .MaxRedirects ; attempt ++ {
1553
+ if attempt > 0 {
1554
+ if err := internal .Sleep (ctx , c .retryBackoff (attempt )); err != nil {
1555
+ setCmdsErr (cmds , err )
1556
+ return err
1578
1557
}
1558
+ }
1579
1559
1580
- failedCmds := newCmdsMap ()
1581
- var wg sync.WaitGroup
1560
+ failedCmds := newCmdsMap ()
1561
+ c .processTxPipelineNode (ctx , node , cmds , failedCmds )
1562
+ var wg sync.WaitGroup
1582
1563
1583
- for node , cmds := range cmdsMap {
1584
- wg .Add (1 )
1585
- go func (node * clusterNode , cmds []Cmder ) {
1586
- defer wg .Done ()
1587
- c .processTxPipelineNode (ctx , node , cmds , failedCmds )
1588
- }(node , cmds )
1589
- }
1564
+ for node , cmds := range cmdsMap {
1565
+ wg .Add (1 )
1566
+ go func (node * clusterNode , cmds []Cmder ) {
1567
+ defer wg .Done ()
1568
+ c .processTxPipelineNode (ctx , node , cmds , failedCmds )
1569
+ }(node , cmds )
1570
+ }
1590
1571
1591
- wg .Wait ()
1592
- if len (failedCmds .m ) == 0 {
1593
- break
1594
- }
1595
- cmdsMap = failedCmds .m
1572
+ wg .Wait ()
1573
+ if len (failedCmds .m ) == 0 {
1574
+ break
1596
1575
}
1576
+ cmdsMap = failedCmds .m
1597
1577
}
1598
1578
1599
1579
return cmdsFirstErr (cmds )
1600
1580
}
1601
1581
1602
- func (c * ClusterClient ) mapCmdsBySlot (cmds []Cmder ) map [int ][]Cmder {
1603
- cmdsMap := make (map [int ][]Cmder )
1604
- preferredRandomSlot := - 1
1582
+ // slottedKeyedCommands returns a map of slot to commands taking into account
1583
+ // only commands that have keys.
1584
+ func (c * ClusterClient ) slottedKeyedCommands (cmds []Cmder ) map [int ][]Cmder {
1585
+ cmdsSlots := map [int ][]Cmder {}
1586
+
1587
+ prefferedRandomSlot := - 1
1605
1588
for _ , cmd := range cmds {
1606
- slot := c .cmdSlot (cmd , preferredRandomSlot )
1607
- if preferredRandomSlot == - 1 {
1608
- preferredRandomSlot = slot
1589
+ if cmdFirstKeyPos (cmd ) == 0 {
1590
+ continue
1609
1591
}
1610
- cmdsMap [slot ] = append (cmdsMap [slot ], cmd )
1611
- }
1612
- return cmdsMap
1613
- }
1614
1592
1615
- // keyedCmds returns all the keyed commands from the cmds slice
1616
- // it determines keyed commands by checking if the command has a first key position
1617
- func (c * ClusterClient ) keyedCmds (cmds []Cmder ) []Cmder {
1618
- keyedCmds := make ([]Cmder , 0 , len (cmds ))
1619
- for _ , cmd := range cmds {
1620
- if cmdFirstKeyPos (cmd ) != 0 {
1621
- keyedCmds = append (keyedCmds , cmd )
1593
+ slot := c .cmdSlot (cmd , prefferedRandomSlot )
1594
+ if prefferedRandomSlot == - 1 {
1595
+ prefferedRandomSlot = slot
1622
1596
}
1597
+
1598
+ cmdsSlots [slot ] = append (cmdsSlots [slot ], cmd )
1623
1599
}
1624
- return keyedCmds
1600
+
1601
+ return cmdsSlots
1625
1602
}
1626
1603
1627
1604
func (c * ClusterClient ) processTxPipelineNode (
0 commit comments