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  }