diff --git a/go.mod b/go.mod index 6c885f198e3..a8fe27ac150 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/golang/snappy v0.0.4 github.com/google/gopacket v1.1.19 github.com/gorilla/mux v1.8.1 - github.com/grafana/dskit v0.0.0-20240219131454-ce15a838bb40 + github.com/grafana/dskit v0.0.0-20240220131618-501176d90c4e github.com/grafana/e2e v0.1.2-0.20240118170847-db90b84177fc github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/json-iterator/go v1.1.12 diff --git a/go.sum b/go.sum index d1ca322f585..af0c5573fd2 100644 --- a/go.sum +++ b/go.sum @@ -495,8 +495,8 @@ github.com/gosimple/slug v1.1.1 h1:fRu/digW+NMwBIP+RmviTK97Ho/bEj/C9swrCspN3D4= github.com/gosimple/slug v1.1.1/go.mod h1:ER78kgg1Mv0NQGlXiDe57DpCyfbNywXXZ9mIorhxAf0= github.com/grafana-tools/sdk v0.0.0-20220919052116-6562121319fc h1:PXZQA2WCxe85Tnn+WEvr8fDpfwibmEPgfgFEaC87G24= github.com/grafana-tools/sdk v0.0.0-20220919052116-6562121319fc/go.mod h1:AHHlOEv1+GGQ3ktHMlhuTUwo3zljV3QJbC0+8o2kn+4= -github.com/grafana/dskit v0.0.0-20240219131454-ce15a838bb40 h1:AzCiKNyJyz+LlhO5qttP8IBZh3cFhZH1rsPUfJa2dTY= -github.com/grafana/dskit v0.0.0-20240219131454-ce15a838bb40/go.mod h1:x5DMwyr1kyirtHOxoFSZ7RnyOgHdGh03ZruupdPetQM= +github.com/grafana/dskit v0.0.0-20240220131618-501176d90c4e h1:DWLOa3YZp6AzcVfswcpu/+YLPGpW2ZXXCyXW4vELk+M= +github.com/grafana/dskit v0.0.0-20240220131618-501176d90c4e/go.mod h1:x5DMwyr1kyirtHOxoFSZ7RnyOgHdGh03ZruupdPetQM= github.com/grafana/e2e v0.1.2-0.20240118170847-db90b84177fc h1:BW+LjKJDz0So5LI8UZfW5neWeKpSkWqhmGjQFzcFfLM= github.com/grafana/e2e v0.1.2-0.20240118170847-db90b84177fc/go.mod h1:JVmqPBe8A/pZWwRoJW5ZjyALeY5OXMzPl7LrVXOdZAI= github.com/grafana/goautoneg v0.0.0-20231010094147-47ce5e72a9ae h1:Yxbw9jKGJVC6qAK5Ubzzb/qZwM6rRMMqaDc/d4Vp3pM= diff --git a/vendor/github.com/grafana/dskit/ring/partition_instance_ring.go b/vendor/github.com/grafana/dskit/ring/partition_instance_ring.go index 72b5c182478..2fb15d8af98 100644 --- a/vendor/github.com/grafana/dskit/ring/partition_instance_ring.go +++ b/vendor/github.com/grafana/dskit/ring/partition_instance_ring.go @@ -3,6 +3,8 @@ package ring import ( "fmt" "time" + + "golang.org/x/exp/slices" ) type PartitionRingReader interface { @@ -48,6 +50,7 @@ func (r *PartitionInstanceRing) GetReplicationSetsForOperation(op Operation) ([] now := time.Now() result := make([]ReplicationSet, 0, len(partitionsRingDesc.Partitions)) + zonesBuffer := make([]string, 0, 3) // Pre-allocate buffer assuming 3 zones. for partitionID := range partitionsRingDesc.Partitions { ownerIDs := partitionsRing.PartitionOwnerIDs(partitionID) @@ -72,10 +75,21 @@ func (r *PartitionInstanceRing) GetReplicationSetsForOperation(op Operation) ([] return nil, fmt.Errorf("partition %d: %w", partitionID, ErrTooManyUnhealthyInstances) } + // Count the number of unique zones among instances. + zonesBuffer = uniqueZonesFromInstances(instances, zonesBuffer[:0]) + uniqueZones := len(zonesBuffer) + result = append(result, ReplicationSet{ - Instances: instances, - MaxUnavailableZones: len(instances) - 1, // We need response from at least 1 owner. - ZoneAwarenessEnabled: true, // Partitions has no concept of zone, but we enable it in order to support ring's requests minimization feature. + Instances: instances, + + // Partitions has no concept of zone, but we enable it in order to support ring's requests + // minimization feature. + ZoneAwarenessEnabled: true, + + // We need response from at least 1 owner. The assumption is that we have 1 owner per zone + // but it's not guaranteed (depends on how the application was deployed). The safest thing + // we can do here is to just request a successful response from at least 1 zone. + MaxUnavailableZones: uniqueZones - 1, }) } return result, nil @@ -122,3 +136,15 @@ func newStaticPartitionRingReader(ring *PartitionRing) staticPartitionRingReader func (m staticPartitionRingReader) PartitionRing() *PartitionRing { return m.ring } + +// uniqueZonesFromInstances returns the unique list of zones among the input instances. The input buf MUST have +// zero length, but could be capacity in order to avoid memory allocations. +func uniqueZonesFromInstances(instances []InstanceDesc, buf []string) []string { + for _, instance := range instances { + if !slices.Contains(buf, instance.Zone) { + buf = append(buf, instance.Zone) + } + } + + return buf +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 756d582b277..ed24641d741 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -538,7 +538,7 @@ github.com/gosimple/slug # github.com/grafana-tools/sdk v0.0.0-20220919052116-6562121319fc ## explicit; go 1.13 github.com/grafana-tools/sdk -# github.com/grafana/dskit v0.0.0-20240219131454-ce15a838bb40 +# github.com/grafana/dskit v0.0.0-20240220131618-501176d90c4e ## explicit; go 1.20 github.com/grafana/dskit/backoff github.com/grafana/dskit/ballast