// sendAndFill is a helper which sends the given batch and fills its results, // returning the appropriate error which is either from the first failing call, // or an "internal" error. func sendAndFill( send func(roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error), b *Batch, ) error { // Errors here will be attached to the results, so we will get them from // the call to fillResults in the regular case in which an individual call // fails. But send() also returns its own errors, so there's some dancing // here to do because we want to run fillResults() so that the individual // result gets initialized with an error from the corresponding call. var ba roachpb.BatchRequest // TODO(tschottdorf): this nonsensical copy is required since (at least at // the time of writing, the chunking and masking in DistSender operates on // the original data (as attested to by a whole bunch of test failures). ba.Requests = append([]roachpb.RequestUnion(nil), b.reqs...) ba.Header = b.Header b.response, b.pErr = send(ba) if b.pErr != nil { // Discard errors from fillResults. _ = b.fillResults() return b.pErr.GoError() } if err := b.fillResults(); err != nil { b.pErr = roachpb.NewError(err) return err } return nil }
// SendWrappedWith is a convenience function which wraps the request in a batch // and sends it via the provided Sender and headers. It returns the unwrapped // response or an error. It's valid to pass a `nil` context; an empty one is // used in that case. func SendWrappedWith( ctx context.Context, sender Sender, h roachpb.Header, args roachpb.Request, ) (roachpb.Response, *roachpb.Error) { ba := roachpb.BatchRequest{} ba.Header = h ba.Add(args) br, pErr := sender.Send(ctx, ba) if pErr != nil { return nil, pErr } unwrappedReply := br.Responses[0].GetInner() header := unwrappedReply.Header() header.Txn = br.Txn unwrappedReply.SetHeader(header) return unwrappedReply, nil }