| 807 | } |
| 808 | |
| 809 | func newClusterState( |
| 810 | nodes *clusterNodes, slots []ClusterSlot, origin string, |
| 811 | ) (*clusterState, error) { |
| 812 | c := clusterState{ |
| 813 | nodes: nodes, |
| 814 | |
| 815 | slots: make([]*clusterSlot, 0, len(slots)), |
| 816 | |
| 817 | generation: nodes.NextGeneration(), |
| 818 | createdAt: time.Now(), |
| 819 | } |
| 820 | |
| 821 | originHost, originPort, _ := net.SplitHostPort(origin) |
| 822 | isLoopbackOrigin := isLoopback(originHost) |
| 823 | |
| 824 | for _, slot := range slots { |
| 825 | var nodes []*clusterNode |
| 826 | for i, slotNode := range slot.Nodes { |
| 827 | // slotNode.Addr is the node address from CLUSTER SLOTS |
| 828 | nodeAddress := slotNode.Addr |
| 829 | addr := nodeAddress |
| 830 | if !isLoopbackOrigin { |
| 831 | addr = replaceLoopbackHost(addr, originHost) |
| 832 | } |
| 833 | // TLS-only clusters (`--port 0 --tls-port 6379`) report port 0 |
| 834 | // in CLUSTER SLOTS. Fall back to the origin port — by definition |
| 835 | // reachable, since it is the port that returned this slot map. |
| 836 | // See https://github.com/redis/go-redis/issues/3726. |
| 837 | addr = replaceZeroPort(addr, originPort) |
| 838 | |
| 839 | node, err := c.nodes.GetOrCreateWithNodeAddress(addr, nodeAddress) |
| 840 | if err != nil { |
| 841 | return nil, err |
| 842 | } |
| 843 | |
| 844 | node.SetGeneration(c.generation) |
| 845 | nodes = append(nodes, node) |
| 846 | |
| 847 | if i == 0 { |
| 848 | c.Masters = appendIfNotExist(c.Masters, node) |
| 849 | } else { |
| 850 | c.Slaves = appendIfNotExist(c.Slaves, node) |
| 851 | } |
| 852 | } |
| 853 | |
| 854 | c.slots = append(c.slots, &clusterSlot{ |
| 855 | start: slot.Start, |
| 856 | end: slot.End, |
| 857 | nodes: nodes, |
| 858 | }) |
| 859 | } |
| 860 | |
| 861 | slices.SortFunc(c.slots, func(a, b *clusterSlot) int { |
| 862 | return cmp.Compare(a.start, b.start) |
| 863 | }) |
| 864 | |
| 865 | time.AfterFunc(time.Minute, func() { |
| 866 | nodes.GC(c.generation) |