github.com/weaviate/weaviate@v1.24.6/usecases/replica/replicator_stream.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package replica 13 14 import ( 15 "fmt" 16 17 "github.com/go-openapi/strfmt" 18 "github.com/weaviate/weaviate/usecases/objects" 19 ) 20 21 type ( 22 // replicatorStream represents an incoming stream of responses 23 // to replication requests sent to replicas 24 replicatorStream struct{} 25 ) 26 27 // readErrors reads errors from incoming responses. 28 // It returns as soon as the specified consistency level l has been reached 29 func (r replicatorStream) readErrors(batchSize int, 30 level int, 31 ch <-chan _Result[SimpleResponse], 32 ) []error { 33 urs := make([]SimpleResponse, 0, level) 34 var firstError error 35 for x := range ch { 36 if x.Err != nil { 37 urs = append(urs, x.Value) 38 if len(x.Value.Errors) == 0 && firstError == nil { 39 firstError = x.Err 40 } 41 } else { 42 level-- 43 if level == 0 { // consistency level reached 44 return make([]error, batchSize) 45 } 46 } 47 } 48 if level > 0 && firstError == nil { 49 firstError = fmt.Errorf("broadcast: %w", errReplicas) 50 } 51 return r.flattenErrors(batchSize, urs, firstError) 52 } 53 54 // readDeletions reads deletion results from incoming responses. 55 // It returns as soon as the specified consistency level l has been reached 56 func (r replicatorStream) readDeletions(batchSize int, 57 level int, 58 ch <-chan _Result[DeleteBatchResponse], 59 ) []objects.BatchSimpleObject { 60 rs := make([]DeleteBatchResponse, 0, level) 61 urs := make([]DeleteBatchResponse, 0, level) 62 var firstError error 63 for x := range ch { 64 if x.Err != nil { 65 urs = append(urs, x.Value) 66 if len(x.Value.Batch) == 0 && firstError == nil { 67 firstError = x.Err 68 } 69 } else { 70 level-- 71 rs = append(rs, x.Value) 72 if level == 0 { // consistency level reached 73 return r.flattenDeletions(batchSize, rs, nil) 74 } 75 } 76 } 77 if level > 0 && firstError == nil { 78 firstError = fmt.Errorf("broadcast: %w", errReplicas) 79 } 80 urs = append(urs, rs...) 81 return r.flattenDeletions(batchSize, urs, firstError) 82 } 83 84 // flattenErrors extracts errors from responses 85 86 func (replicatorStream) flattenErrors(batchSize int, 87 rs []SimpleResponse, 88 defaultErr error, 89 ) []error { 90 errs := make([]error, batchSize) 91 n := 0 92 for _, resp := range rs { 93 if len(resp.Errors) != batchSize { 94 continue 95 } 96 n++ 97 for i, err := range resp.Errors { 98 if !err.Empty() && errs[i] == nil { 99 errs[i] = err.Clone() 100 } 101 } 102 } 103 if n == 0 || n != len(rs) { 104 for i := range errs { 105 if errs[i] == nil { 106 errs[i] = defaultErr 107 } 108 } 109 } 110 return errs 111 } 112 113 // flattenDeletions extracts deletion results from responses 114 func (replicatorStream) flattenDeletions(batchSize int, 115 rs []DeleteBatchResponse, 116 defaultErr error, 117 ) []objects.BatchSimpleObject { 118 ret := make([]objects.BatchSimpleObject, batchSize) 119 n := 0 120 for _, resp := range rs { 121 if len(resp.Batch) != batchSize { 122 continue 123 } 124 n++ 125 for i, x := range resp.Batch { 126 if !x.Error.Empty() && ret[i].Err == nil { 127 ret[i].Err = x.Error.Clone() 128 } 129 if ret[i].UUID == "" && x.UUID != "" { 130 ret[i].UUID = strfmt.UUID(x.UUID) 131 } 132 } 133 } 134 if n == 0 || n != len(rs) { 135 for i := range ret { 136 if ret[i].Err == nil { 137 ret[i].Err = defaultErr 138 } 139 } 140 } 141 return ret 142 } 143 144 func firstError(es []error) error { 145 for _, e := range es { 146 if e != nil { 147 return e 148 } 149 } 150 return nil 151 } 152 153 func firstBatchError(xs []objects.BatchSimpleObject) error { 154 for _, x := range xs { 155 if x.Err != nil { 156 return x.Err 157 } 158 } 159 return nil 160 }