// UpdateForBatch updates the first argument (the header of a request contained // in a batch) from the second one (the batch header), returning an error when // inconsistencies are found. // It is checked that the individual call does not have a UserPriority // or Txn set that differs from the batch's. // TODO(tschottdorf): will go with #2143. func updateForBatch(args roachpb.Request, bHeader roachpb.BatchRequest_Header) error { // Disallow transaction, user and priority on individual calls, unless // equal. aHeader := args.Header() if aPrio := aHeader.GetUserPriority(); aPrio != roachpb.Default_RequestHeader_UserPriority && aPrio != bHeader.GetUserPriority() { return util.Errorf("conflicting user priority on call in batch") } aHeader.UserPriority = bHeader.UserPriority aHeader.Txn = bHeader.Txn // reqs always take Txn from batch return nil }
// SendWrappedAt is a convenience function which wraps the request in a batch // and sends it via the provided Sender at the given timestamp. It returns the // unwrapped response or an error. It's valid to pass a `nil` context; // context.Background() is used in that case. func SendWrappedAt(sender Sender, ctx context.Context, ts roachpb.Timestamp, args roachpb.Request) (roachpb.Response, error) { if ctx == nil { ctx = context.Background() } ba, unwrap := func(args roachpb.Request) (*roachpb.BatchRequest, func(*roachpb.BatchResponse) roachpb.Response) { ba := &roachpb.BatchRequest{} ba.Timestamp = ts { h := args.Header() ba.Key, ba.EndKey = h.Key, h.EndKey ba.CmdID = h.CmdID ba.Replica = h.Replica ba.RangeID = h.RangeID ba.UserPriority = h.UserPriority ba.Txn = h.Txn ba.ReadConsistency = h.ReadConsistency } ba.Add(args) return ba, func(br *roachpb.BatchResponse) roachpb.Response { unwrappedReply := br.Responses[0].GetInner() // The ReplyTxn is propagated from one response to the next request, // and we adopt the mechanism that whenever the Txn changes, it needs // to be set in the reply, for example to ratchet up the transaction // timestamp on writes when necessary. // This is internally necessary to sequentially execute the batch, // so it makes some sense to take the burden of updating the Txn // from TxnCoordSender - it will only need to act on retries/aborts // in the future. unwrappedReply.Header().Txn = br.Txn return unwrappedReply } }(args) br, pErr := sender.Send(ctx, *ba) if err := pErr.GoError(); err != nil { return nil, err } return unwrap(br), nil }