github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/memoryengine/request.go (about)

     1  // Copyright 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package memoryengine
    16  
    17  import (
    18  	"context"
    19  	"encoding"
    20  	"time"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    23  	"github.com/matrixorigin/matrixone/pkg/pb/txn"
    24  	"github.com/matrixorigin/matrixone/pkg/txn/client"
    25  	"github.com/matrixorigin/matrixone/pkg/txn/rpc"
    26  )
    27  
    28  func DoTxnRequest[
    29  	Resp any, PResp interface {
    30  		// anonymous constraint
    31  		encoding.BinaryUnmarshaler
    32  		// make Resp convertible to its pointer type
    33  		*Resp
    34  	},
    35  	Req any, PReq interface {
    36  		// anonymous constraint
    37  		encoding.BinaryMarshaler
    38  		// make Req convertible to its pointer type
    39  		*Req
    40  	},
    41  ](
    42  	ctx context.Context,
    43  	txnOperator client.TxnOperator,
    44  	isRead bool,
    45  	shardsFunc shardsFunc,
    46  	op uint32,
    47  	preq PReq,
    48  ) (
    49  	resps []Resp,
    50  	err error,
    51  ) {
    52  
    53  	if ctx == nil {
    54  		panic("context should not be nil")
    55  	}
    56  
    57  	shards, err := shardsFunc()
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	if provider, ok := txnOperator.(OperationHandlerProvider); ok {
    63  		for _, shard := range shards {
    64  			handler, meta := provider.GetOperationHandler(shard)
    65  			var presp PResp = new(Resp)
    66  			e := handle(ctx, handler, meta, shard, op, preq, presp)
    67  			resps = append(resps, *presp)
    68  			if e != nil {
    69  				err = e
    70  			}
    71  		}
    72  		return
    73  	}
    74  
    75  	requests := make([]txn.TxnRequest, 0, len(shards))
    76  	for _, shard := range shards {
    77  		buf, err := preq.MarshalBinary()
    78  		if err != nil {
    79  			panic(err)
    80  		}
    81  		requests = append(requests, txn.TxnRequest{
    82  			CNRequest: &txn.CNOpRequest{
    83  				OpCode:  op,
    84  				Payload: buf,
    85  				Target:  shard,
    86  			},
    87  			Options: &txn.TxnRequestOptions{
    88  				RetryCodes: []int32{
    89  					// tn shard not found
    90  					int32(moerr.ErrTNShardNotFound),
    91  				},
    92  				RetryInterval: int64(time.Second),
    93  			},
    94  		})
    95  	}
    96  
    97  	ctx, cancel := context.WithTimeout(ctx, time.Minute*10)
    98  	defer cancel()
    99  
   100  	var result *rpc.SendResult
   101  	if isRead {
   102  		result, err = txnOperator.Read(ctx, requests)
   103  		if err != nil {
   104  			return
   105  		}
   106  	} else {
   107  		result, err = txnOperator.Write(ctx, requests)
   108  		if err != nil {
   109  			return
   110  		}
   111  	}
   112  	for _, resp := range result.Responses {
   113  		if resp.TxnError != nil {
   114  			err = resp.TxnError.UnwrapError()
   115  			return
   116  		}
   117  	}
   118  
   119  	for _, res := range result.Responses {
   120  		var presp PResp = new(Resp)
   121  		err = presp.UnmarshalBinary(res.CNOpResponse.Payload)
   122  		if err != nil {
   123  			return
   124  		}
   125  		resps = append(resps, *presp)
   126  	}
   127  
   128  	return
   129  }