mirror of https://github.com/tikv/client-java.git
Fix pd request throws invalid store id (#337)
This commit is contained in:
parent
e87bb8afd9
commit
5bbe72eeaa
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2021 PingCAP, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.tikv.common.exception;
|
||||
|
||||
public class InvalidStoreException extends TiKVException {
|
||||
|
||||
public InvalidStoreException(long storeId) {
|
||||
super(String.format("Invalid storeId: %d", storeId));
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ package org.tikv.common.operation;
|
|||
|
||||
import static org.tikv.common.pd.PDError.buildFromPdpbError;
|
||||
|
||||
import io.grpc.StatusRuntimeException;
|
||||
import java.util.function.Function;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
|
@ -74,6 +75,10 @@ public class PDErrorHandler<RespT> implements ErrorHandler<RespT> {
|
|||
|
||||
@Override
|
||||
public boolean handleRequestError(BackOffer backOffer, Exception e) {
|
||||
// store id is not found
|
||||
if (e instanceof StatusRuntimeException && e.getMessage().contains("invalid store ID")) {
|
||||
return false;
|
||||
}
|
||||
backOffer.doBackOff(BackOffFunction.BackOffFuncType.BoPDRPC, e);
|
||||
client.updateLeaderOrforwardFollower();
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import org.slf4j.LoggerFactory;
|
|||
import org.tikv.common.ReadOnlyPDClient;
|
||||
import org.tikv.common.TiConfiguration;
|
||||
import org.tikv.common.exception.GrpcException;
|
||||
import org.tikv.common.exception.InvalidStoreException;
|
||||
import org.tikv.common.exception.TiClientInternalException;
|
||||
import org.tikv.common.util.BackOffer;
|
||||
import org.tikv.common.util.ChannelFactory;
|
||||
|
|
@ -152,9 +153,6 @@ public class RegionManager {
|
|||
if (storeType == TiStoreType.TiKV) {
|
||||
Peer peer = region.getCurrentReplica();
|
||||
store = getStoreById(peer.getStoreId(), backOffer);
|
||||
if (store == null) {
|
||||
cache.clearAll();
|
||||
}
|
||||
} else {
|
||||
outerLoop:
|
||||
for (Peer peer : region.getLearnerList()) {
|
||||
|
|
@ -168,16 +166,11 @@ public class RegionManager {
|
|||
}
|
||||
}
|
||||
if (store == null) {
|
||||
// clear the region cache so we may get the learner peer next time
|
||||
// clear the region cache, so we may get the learner peer next time
|
||||
cache.invalidateRegion(region);
|
||||
}
|
||||
}
|
||||
|
||||
if (store == null) {
|
||||
throw new TiClientInternalException(
|
||||
"Cannot find valid store on " + storeType + " for region " + region.toString());
|
||||
}
|
||||
|
||||
return Pair.create(region, store);
|
||||
}
|
||||
|
||||
|
|
@ -200,13 +193,20 @@ public class RegionManager {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public TiStore getStoreById(long id, BackOffer backOffer) {
|
||||
private TiStore getStoreByIdWithBackOff(long id, BackOffer backOffer) {
|
||||
try {
|
||||
TiStore store = cache.getStoreById(id);
|
||||
if (store == null) {
|
||||
store = new TiStore(pdClient.getStore(backOffer, id));
|
||||
}
|
||||
// if we did not get store info from pd, remove store from cache
|
||||
if (store.getStore() == null) {
|
||||
logger.warn(String.format("failed to get store %d from pd", id));
|
||||
return null;
|
||||
}
|
||||
// if the store is already tombstone, remove store from cache
|
||||
if (store.getStore().getState().equals(StoreState.Tombstone)) {
|
||||
logger.warn(String.format("store %d is tombstone", id));
|
||||
return null;
|
||||
}
|
||||
if (cache.putStore(id, store) && storeChecker != null) {
|
||||
|
|
@ -222,6 +222,16 @@ public class RegionManager {
|
|||
return getStoreById(id, defaultBackOff());
|
||||
}
|
||||
|
||||
public TiStore getStoreById(long id, BackOffer backOffer) {
|
||||
TiStore store = getStoreByIdWithBackOff(id, backOffer);
|
||||
if (store == null) {
|
||||
logger.warn(String.format("failed to fetch store %d, the store may be missing", id));
|
||||
cache.clearAll();
|
||||
throw new InvalidStoreException(id);
|
||||
}
|
||||
return store;
|
||||
}
|
||||
|
||||
public void onRegionStale(TiRegion region) {
|
||||
cache.invalidateRegion(region);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,9 +146,8 @@ public class RawKVClient implements AutoCloseable {
|
|||
ConcreteBackOffer.newDeadlineBackOff(conf.getRawKVWriteTimeoutInMS(), slowLog);
|
||||
try {
|
||||
while (true) {
|
||||
RegionStoreClient client = clientBuilder.build(key, backOffer);
|
||||
slowLog.addProperty("region", client.getRegion().toString());
|
||||
try {
|
||||
try (RegionStoreClient client = clientBuilder.build(key, backOffer)) {
|
||||
slowLog.addProperty("region", client.getRegion().toString());
|
||||
client.rawPut(backOffer, key, value, ttl, atomic);
|
||||
RAW_REQUEST_SUCCESS.labels(label).inc();
|
||||
return;
|
||||
|
|
@ -203,9 +202,8 @@ public class RawKVClient implements AutoCloseable {
|
|||
ConcreteBackOffer.newDeadlineBackOff(conf.getRawKVWriteTimeoutInMS(), slowLog);
|
||||
try {
|
||||
while (true) {
|
||||
RegionStoreClient client = clientBuilder.build(key, backOffer);
|
||||
slowLog.addProperty("region", client.getRegion().toString());
|
||||
try {
|
||||
try (RegionStoreClient client = clientBuilder.build(key, backOffer)) {
|
||||
slowLog.addProperty("region", client.getRegion().toString());
|
||||
ByteString result = client.rawPutIfAbsent(backOffer, key, value, ttl);
|
||||
RAW_REQUEST_SUCCESS.labels(label).inc();
|
||||
return result;
|
||||
|
|
@ -311,9 +309,8 @@ public class RawKVClient implements AutoCloseable {
|
|||
ConcreteBackOffer.newDeadlineBackOff(conf.getRawKVReadTimeoutInMS(), slowLog);
|
||||
try {
|
||||
while (true) {
|
||||
RegionStoreClient client = clientBuilder.build(key, backOffer);
|
||||
slowLog.addProperty("region", client.getRegion().toString());
|
||||
try {
|
||||
try (RegionStoreClient client = clientBuilder.build(key, backOffer)) {
|
||||
slowLog.addProperty("region", client.getRegion().toString());
|
||||
ByteString result = client.rawGet(backOffer, key);
|
||||
RAW_REQUEST_SUCCESS.labels(label).inc();
|
||||
return result;
|
||||
|
|
@ -434,9 +431,8 @@ public class RawKVClient implements AutoCloseable {
|
|||
ConcreteBackOffer.newDeadlineBackOff(conf.getRawKVReadTimeoutInMS(), slowLog);
|
||||
try {
|
||||
while (true) {
|
||||
RegionStoreClient client = clientBuilder.build(key, backOffer);
|
||||
slowLog.addProperty("region", client.getRegion().toString());
|
||||
try {
|
||||
try (RegionStoreClient client = clientBuilder.build(key, backOffer)) {
|
||||
slowLog.addProperty("region", client.getRegion().toString());
|
||||
Long result = client.rawGetKeyTTL(backOffer, key);
|
||||
RAW_REQUEST_SUCCESS.labels(label).inc();
|
||||
return result;
|
||||
|
|
@ -709,9 +705,8 @@ public class RawKVClient implements AutoCloseable {
|
|||
ConcreteBackOffer.newDeadlineBackOff(conf.getRawKVWriteTimeoutInMS(), slowLog);
|
||||
try {
|
||||
while (true) {
|
||||
RegionStoreClient client = clientBuilder.build(key, backOffer);
|
||||
slowLog.addProperty("region", client.getRegion().toString());
|
||||
try {
|
||||
try (RegionStoreClient client = clientBuilder.build(key, backOffer)) {
|
||||
slowLog.addProperty("region", client.getRegion().toString());
|
||||
client.rawDelete(backOffer, key, atomic);
|
||||
RAW_REQUEST_SUCCESS.labels(label).inc();
|
||||
return;
|
||||
|
|
@ -887,8 +882,8 @@ public class RawKVClient implements AutoCloseable {
|
|||
|
||||
private Pair<List<Batch>, List<KvPair>> doSendBatchGetInBatchesWithRetry(
|
||||
BackOffer backOffer, Batch batch) {
|
||||
RegionStoreClient client = clientBuilder.build(batch.getRegion(), backOffer);
|
||||
try {
|
||||
|
||||
try (RegionStoreClient client = clientBuilder.build(batch.getRegion(), backOffer)) {
|
||||
List<KvPair> partialResult = client.rawBatchGet(backOffer, batch.getKeys());
|
||||
return Pair.create(new ArrayList<>(), partialResult);
|
||||
} catch (final TiKVException e) {
|
||||
|
|
@ -939,8 +934,7 @@ public class RawKVClient implements AutoCloseable {
|
|||
|
||||
private List<Batch> doSendBatchDeleteInBatchesWithRetry(
|
||||
BackOffer backOffer, Batch batch, boolean atomic) {
|
||||
RegionStoreClient client = clientBuilder.build(batch.getRegion(), backOffer);
|
||||
try {
|
||||
try (RegionStoreClient client = clientBuilder.build(batch.getRegion(), backOffer)) {
|
||||
client.rawBatchDelete(backOffer, batch.getKeys(), atomic);
|
||||
return new ArrayList<>();
|
||||
} catch (final TiKVException e) {
|
||||
|
|
|
|||
|
|
@ -161,7 +161,12 @@ public class RegionManagerTest extends PDMockServerTest {
|
|||
StoreState.Tombstone,
|
||||
GrpcUtils.makeStoreLabel("k1", "v1"),
|
||||
GrpcUtils.makeStoreLabel("k2", "v2"))));
|
||||
assertNull(mgr.getStoreById(storeId + 1));
|
||||
|
||||
try {
|
||||
mgr.getStoreById(storeId + 1);
|
||||
fail();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
mgr.invalidateStore(storeId);
|
||||
try {
|
||||
|
|
|
|||
Loading…
Reference in New Issue