github.com/matrixorigin/matrixone@v0.7.0/pkg/dnservice/store_rpc_handler.go (about) 1 // Copyright 2021 - 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 dnservice 16 17 import ( 18 "context" 19 "time" 20 21 "github.com/matrixorigin/matrixone/pkg/common/moerr" 22 "github.com/matrixorigin/matrixone/pkg/pb/metadata" 23 "github.com/matrixorigin/matrixone/pkg/pb/txn" 24 "github.com/matrixorigin/matrixone/pkg/txn/rpc" 25 ) 26 27 const ( 28 defaultRetryInterval = time.Millisecond * 100 29 ) 30 31 func (s *store) registerRPCHandlers() { 32 // request from CN node 33 s.server.RegisterMethodHandler(txn.TxnMethod_Read, s.handleRead) 34 s.server.RegisterMethodHandler(txn.TxnMethod_Write, s.handleWrite) 35 s.server.RegisterMethodHandler(txn.TxnMethod_Commit, s.handleCommit) 36 s.server.RegisterMethodHandler(txn.TxnMethod_Rollback, s.handleRollback) 37 38 // request from other DN node 39 s.server.RegisterMethodHandler(txn.TxnMethod_Prepare, s.handlePrepare) 40 s.server.RegisterMethodHandler(txn.TxnMethod_CommitDNShard, s.handleCommitDNShard) 41 s.server.RegisterMethodHandler(txn.TxnMethod_RollbackDNShard, s.handleRollbackDNShard) 42 s.server.RegisterMethodHandler(txn.TxnMethod_GetStatus, s.handleGetStatus) 43 44 // debug request 45 s.server.RegisterMethodHandler(txn.TxnMethod_DEBUG, s.handleDebug) 46 } 47 48 func (s *store) dispatchLocalRequest(shard metadata.DNShard) rpc.TxnRequestHandleFunc { 49 // DNShard not found, TxnSender will RPC call 50 r := s.getReplica(shard.ShardID) 51 if r == nil { 52 return nil 53 } 54 return r.handleLocalRequest 55 } 56 57 func (s *store) handleRead(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) error { 58 return s.handleWithRetry(ctx, request, response, s.doRead) 59 } 60 61 func (s *store) handleWrite(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) error { 62 return s.handleWithRetry(ctx, request, response, s.doWrite) 63 } 64 65 func (s *store) handleDebug(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) error { 66 return s.handleWithRetry(ctx, request, response, s.doDebug) 67 } 68 69 func (s *store) doRead(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) error { 70 r := s.validDNShard(ctx, request, response) 71 if r == nil { 72 return nil 73 } 74 r.waitStarted() 75 76 prepareResponse(request, response) 77 return r.service.Read(ctx, request, response) 78 } 79 80 func (s *store) doWrite(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) error { 81 r := s.validDNShard(ctx, request, response) 82 if r == nil { 83 return nil 84 } 85 r.waitStarted() 86 prepareResponse(request, response) 87 return r.service.Write(ctx, request, response) 88 } 89 90 func (s *store) doDebug(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) error { 91 r := s.validDNShard(ctx, request, response) 92 if r == nil { 93 return nil 94 } 95 r.waitStarted() 96 97 prepareResponse(request, response) 98 return r.service.Debug(ctx, request, response) 99 } 100 101 func (s *store) handleCommit(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) error { 102 r := s.validDNShard(ctx, request, response) 103 if r == nil { 104 return nil 105 } 106 r.waitStarted() 107 prepareResponse(request, response) 108 return r.service.Commit(ctx, request, response) 109 } 110 111 func (s *store) handleRollback(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) error { 112 r := s.validDNShard(ctx, request, response) 113 if r == nil { 114 return nil 115 } 116 r.waitStarted() 117 prepareResponse(request, response) 118 return r.service.Rollback(ctx, request, response) 119 } 120 121 func (s *store) handlePrepare(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) error { 122 r := s.validDNShard(ctx, request, response) 123 if r == nil { 124 return nil 125 } 126 r.waitStarted() 127 prepareResponse(request, response) 128 return r.service.Prepare(ctx, request, response) 129 } 130 131 func (s *store) handleCommitDNShard(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) error { 132 r := s.validDNShard(ctx, request, response) 133 if r == nil { 134 return nil 135 } 136 r.waitStarted() 137 prepareResponse(request, response) 138 return r.service.CommitDNShard(ctx, request, response) 139 } 140 141 func (s *store) handleRollbackDNShard(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) error { 142 r := s.validDNShard(ctx, request, response) 143 if r == nil { 144 return nil 145 } 146 r.waitStarted() 147 prepareResponse(request, response) 148 return r.service.RollbackDNShard(ctx, request, response) 149 } 150 151 func (s *store) handleGetStatus(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) error { 152 r := s.validDNShard(ctx, request, response) 153 if r == nil { 154 return nil 155 } 156 r.waitStarted() 157 prepareResponse(request, response) 158 return r.service.GetStatus(ctx, request, response) 159 } 160 161 func (s *store) validDNShard(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) *replica { 162 shard := request.GetTargetDN() 163 r := s.getReplica(shard.ShardID) 164 if r == nil || 165 r.shard.GetReplicaID() != shard.GetReplicaID() { 166 response.TxnError = txn.WrapError(moerr.NewDNShardNotFound(ctx, s.cfg.UUID, shard.ShardID), 0) 167 return nil 168 } 169 return r 170 } 171 172 func prepareResponse(request *txn.TxnRequest, response *txn.TxnResponse) { 173 response.Method = request.Method 174 response.Flag = request.Flag 175 response.RequestID = request.RequestID 176 } 177 178 func (s *store) handleWithRetry(ctx context.Context, 179 request *txn.TxnRequest, 180 response *txn.TxnResponse, 181 delegate rpc.TxnRequestHandleFunc) error { 182 for { 183 response.Reset() 184 err := delegate(ctx, request, response) 185 if err != nil { 186 return err 187 } 188 189 if !s.maybeRetry(ctx, request, response) { 190 return nil 191 } 192 } 193 } 194 195 func (s *store) maybeRetry(ctx context.Context, request *txn.TxnRequest, response *txn.TxnResponse) bool { 196 if response.TxnError == nil { 197 return false 198 } 199 if request.Options == nil { 200 return false 201 } 202 if len(request.Options.RetryCodes) == 0 { 203 return false 204 } 205 206 select { 207 case <-ctx.Done(): 208 return false 209 default: 210 for _, code := range request.Options.RetryCodes { 211 if code == int32(response.TxnError.TxnErrCode) { 212 wait := time.Duration(request.Options.RetryInterval) 213 if wait == 0 { 214 wait = defaultRetryInterval 215 } 216 time.Sleep(wait) 217 return true 218 } 219 } 220 return false 221 } 222 }