Search in sources :

Example 1 with FutureTransformer

use of com.twitter.util.FutureTransformer in project linden by XiaoMi.

the class CoreLindenCluster method delete.

@Override
public Response delete(LindenDeleteRequest request) throws IOException {
    List<Future<BoxedUnit>> futures = new ArrayList<>();
    List<String> hosts = new ArrayList<>();
    final StringBuilder errorInfo = new StringBuilder();
    Set<Integer> routeIds = null;
    if (request.isSetRouteParam()) {
        routeIds = new HashSet<>();
        for (final ShardRouteParam routeParam : request.getRouteParam().getShardParams()) {
            routeIds.add(routeParam.getShardId());
        }
    }
    for (final Map.Entry<Integer, ShardClient> entry : clients.entrySet()) {
        if (routeIds != null && !routeIds.contains(entry.getKey())) {
            continue;
        }
        if (entry.getValue().isAvailable()) {
            List<Map.Entry<String, Future<Response>>> hostFuturePairs = entry.getValue().delete(request);
            for (final Map.Entry<String, Future<Response>> hostFuturePair : hostFuturePairs) {
                hosts.add(hostFuturePair.getKey());
                futures.add(hostFuturePair.getValue().transformedBy(new FutureTransformer<Response, BoxedUnit>() {

                    @Override
                    public BoxedUnit map(Response response) {
                        if (!response.isSuccess()) {
                            synchronized (errorInfo) {
                                LOGGER.error("Shard [{}] host [{}] failed to get delete response : {}", entry.getKey(), hostFuturePair.getKey(), response.getError());
                                errorInfo.append("Shard " + entry.getKey() + " host " + hostFuturePair.getKey() + ":" + response.getError() + ";");
                            }
                        }
                        return BoxedUnit.UNIT;
                    }

                    @Override
                    public BoxedUnit handle(Throwable t) {
                        LOGGER.error("Shard [{}] host [{}] failed to get delete response : {}", entry.getKey(), hostFuturePair.getKey(), Throwables.getStackTraceAsString(t));
                        errorInfo.append("Shard " + entry.getKey() + " host " + hostFuturePair.getKey() + ":" + Throwables.getStackTraceAsString(t) + ";");
                        return BoxedUnit.UNIT;
                    }
                }));
            }
        }
    }
    Future<List<BoxedUnit>> collected = Future.collect(futures);
    try {
        if (clusterFutureAwaitTimeout == 0) {
            Await.result(collected);
        } else {
            Await.result(collected, Duration.apply(clusterFutureAwaitTimeout, TimeUnit.MILLISECONDS));
        }
        if (errorInfo.length() > 0) {
            return ResponseUtils.buildFailedResponse("Delete failed: " + errorInfo.toString());
        }
        return ResponseUtils.SUCCESS;
    } catch (Exception e) {
        LOGGER.error("Failed to get all delete responses, exception: {}", Throwables.getStackTraceAsString(e));
        LOGGER.error(getHostFutureInfo(hosts, futures));
        return ResponseUtils.buildFailedResponse(e);
    }
}
Also used : FutureTransformer(com.twitter.util.FutureTransformer) ArrayList(java.util.ArrayList) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) Response(com.xiaomi.linden.thrift.common.Response) ShardRouteParam(com.xiaomi.linden.thrift.common.ShardRouteParam) Future(com.twitter.util.Future) ArrayList(java.util.ArrayList) List(java.util.List) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 2 with FutureTransformer

use of com.twitter.util.FutureTransformer in project linden by XiaoMi.

the class CoreLindenCluster method executeCommand.

@Override
public Response executeCommand(final String command) throws IOException {
    LOGGER.info("Receive cluster command {}", command);
    List<Future<BoxedUnit>> futures = new ArrayList<>();
    List<String> hosts = new ArrayList<>();
    final StringBuilder errorInfo = new StringBuilder();
    JSONObject jsonCmd = JSONObject.parseObject(command);
    Integer shardId = jsonCmd.getInteger(SHARD);
    for (final Map.Entry<Integer, ShardClient> entry : clients.entrySet()) {
        ShardClient shardClient = entry.getValue();
        if (shardId != null && shardId != shardClient.getShardId()) {
            continue;
        }
        if (shardClient.isAvailable()) {
            final List<Map.Entry<String, Future<Response>>> hostFuturePairs = shardClient.executeCommand(jsonCmd);
            for (final Map.Entry<String, Future<Response>> hostFuturePair : hostFuturePairs) {
                hosts.add(hostFuturePair.getKey());
                futures.add(hostFuturePair.getValue().transformedBy(new FutureTransformer<Response, BoxedUnit>() {

                    @Override
                    public BoxedUnit map(Response response) {
                        if (!response.isSuccess()) {
                            LOGGER.error("Shard [{}] host [{}] failed to execute command {} error: {}", entry.getKey(), hostFuturePair.getKey(), command, response.getError());
                            synchronized (errorInfo) {
                                errorInfo.append("Shard " + entry.getKey() + " host " + hostFuturePair.getKey() + ":" + response.getError() + ";");
                            }
                        }
                        return BoxedUnit.UNIT;
                    }

                    @Override
                    public BoxedUnit handle(Throwable t) {
                        LOGGER.error("Shard [{}] host [{}] failed to execute command {} throwable: {}\"", entry.getKey(), hostFuturePair.getKey(), command, Throwables.getStackTraceAsString(t));
                        synchronized (errorInfo) {
                            errorInfo.append("Shard " + entry.getKey() + " host " + hostFuturePair.getKey() + ":" + Throwables.getStackTraceAsString(t) + ";");
                        }
                        return BoxedUnit.UNIT;
                    }
                }));
            }
        }
    }
    try {
        Future<List<BoxedUnit>> collected = Future.collect(futures);
        if (clusterFutureAwaitTimeout == 0) {
            Await.result(collected);
        } else {
            // executeCommand may take a very long time, so set timeout to 30min specially
            Await.result(collected, Duration.apply(30, TimeUnit.MINUTES));
        }
        if (errorInfo.length() > 0) {
            return ResponseUtils.buildFailedResponse("command " + command + " failed: " + errorInfo.toString());
        }
        LOGGER.error("Cluster command {} succeeded", command);
        return ResponseUtils.SUCCESS;
    } catch (Exception e) {
        LOGGER.error("Cluster command {} failed {}", command, Throwables.getStackTraceAsString(e));
        LOGGER.error(getHostFutureInfo(hosts, futures));
        return ResponseUtils.buildFailedResponse(e);
    }
}
Also used : FutureTransformer(com.twitter.util.FutureTransformer) ArrayList(java.util.ArrayList) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) Response(com.xiaomi.linden.thrift.common.Response) JSONObject(com.alibaba.fastjson.JSONObject) Future(com.twitter.util.Future) ArrayList(java.util.ArrayList) List(java.util.List) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 3 with FutureTransformer

use of com.twitter.util.FutureTransformer in project linden by XiaoMi.

the class CoreLindenCluster method index.

@Override
public Response index(String content) throws IOException {
    List<Future<BoxedUnit>> futures = new ArrayList<>();
    List<String> hosts = new ArrayList<>();
    final StringBuilder errorInfo = new StringBuilder();
    LindenIndexRequest indexRequest = LindenIndexRequestParser.parse(lindenConfig.getSchema(), content);
    for (final Map.Entry<Integer, ShardClient> entry : clients.entrySet()) {
        ShardClient shardClient = entry.getValue();
        if (shardClient.isAvailable()) {
            if (shardingStrategy.accept(indexRequest.getId(), indexRequest.getRouteParam(), shardClient.getShardId())) {
                final List<Map.Entry<String, Future<Response>>> hostFuturePairs = shardClient.index(content);
                for (final Map.Entry<String, Future<Response>> hostFuturePair : hostFuturePairs) {
                    hosts.add(hostFuturePair.getKey());
                    futures.add(hostFuturePair.getValue().transformedBy(new FutureTransformer<Response, BoxedUnit>() {

                        @Override
                        public BoxedUnit map(Response response) {
                            if (!response.isSuccess()) {
                                LOGGER.error("Shard [{}] host [{}] failed to get index response : {}", entry.getKey(), hostFuturePair.getKey(), response.getError());
                                synchronized (errorInfo) {
                                    errorInfo.append("Shard " + entry.getKey() + " host " + hostFuturePair.getKey() + ":" + response.getError() + ";");
                                }
                            }
                            return BoxedUnit.UNIT;
                        }

                        @Override
                        public BoxedUnit handle(Throwable t) {
                            LOGGER.error("Shard [{}] host [{}] failed to get index response : {}", entry.getKey(), hostFuturePair.getKey(), Throwables.getStackTraceAsString(t));
                            synchronized (errorInfo) {
                                errorInfo.append("Shard " + entry.getKey() + " host " + hostFuturePair.getKey() + ":" + Throwables.getStackTraceAsString(t) + ";");
                            }
                            return BoxedUnit.UNIT;
                        }
                    }));
                }
            }
        }
    }
    try {
        Future<List<BoxedUnit>> collected = Future.collect(futures);
        if (clusterFutureAwaitTimeout == 0) {
            Await.result(collected);
        } else {
            Await.result(collected, Duration.apply(clusterFutureAwaitTimeout, TimeUnit.MILLISECONDS));
        }
        if (errorInfo.length() > 0) {
            return ResponseUtils.buildFailedResponse("Index failed: " + errorInfo.toString());
        }
        return ResponseUtils.SUCCESS;
    } catch (Exception e) {
        LOGGER.error("Handle request failed, content : {} - {}", content, Throwables.getStackTraceAsString(e));
        LOGGER.error(getHostFutureInfo(hosts, futures));
        return ResponseUtils.buildFailedResponse(e);
    }
}
Also used : LindenIndexRequest(com.xiaomi.linden.thrift.common.LindenIndexRequest) FutureTransformer(com.twitter.util.FutureTransformer) ArrayList(java.util.ArrayList) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) Response(com.xiaomi.linden.thrift.common.Response) Future(com.twitter.util.Future) ArrayList(java.util.ArrayList) List(java.util.List) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 4 with FutureTransformer

use of com.twitter.util.FutureTransformer in project linden by XiaoMi.

the class CoreLindenCluster method coreSearch.

public LindenResult coreSearch(final LindenSearchRequest request) throws IOException {
    List<Future<BoxedUnit>> futures = new ArrayList<>();
    List<String> hosts = new ArrayList<>();
    final List<LindenResult> resultList = new ArrayList<>();
    if (request.isSetRouteParam() && request.getRouteParam().isSetShardParams()) {
        for (final ShardRouteParam routeParam : request.getRouteParam().getShardParams()) {
            ShardClient client = clients.get(routeParam.getShardId());
            if (client != null && client.isAvailable()) {
                LindenSearchRequest subRequest = request;
                if (routeParam.isSetEarlyParam()) {
                    subRequest = new LindenSearchRequest(request);
                    subRequest.setEarlyParam(routeParam.getEarlyParam());
                }
                final Map.Entry<String, Future<LindenResult>> hostFuturePair = client.search(subRequest);
                hosts.add(hostFuturePair.getKey());
                futures.add(hostFuturePair.getValue().transformedBy(new FutureTransformer<LindenResult, BoxedUnit>() {

                    @Override
                    public BoxedUnit map(LindenResult lindenResult) {
                        synchronized (resultList) {
                            resultList.add(lindenResult);
                            if (!lindenResult.isSuccess()) {
                                LOGGER.error("Shard [{}] host [{}] failed to get search result : {}", routeParam.getShardId(), hostFuturePair.getKey(), lindenResult.getError());
                            }
                        }
                        return BoxedUnit.UNIT;
                    }

                    @Override
                    public BoxedUnit handle(Throwable t) {
                        LOGGER.error("Shard [{}] host [{}] failed to get search result : {}", routeParam.getShardId(), hostFuturePair.getKey(), Throwables.getStackTraceAsString(t));
                        return BoxedUnit.UNIT;
                    }
                }));
            } else {
                LOGGER.warn("Route to Shard [{}] failed.", routeParam.getShardId());
            }
        }
    } else {
        LindenSearchRequest subRequest = request;
        for (final Map.Entry<Integer, ShardClient> entry : clients.entrySet()) {
            if (entry.getValue().isAvailable()) {
                final Map.Entry<String, Future<LindenResult>> hostFuturePair = entry.getValue().search(subRequest);
                hosts.add(hostFuturePair.getKey());
                futures.add(hostFuturePair.getValue().transformedBy(new FutureTransformer<LindenResult, BoxedUnit>() {

                    @Override
                    public BoxedUnit map(LindenResult lindenResult) {
                        synchronized (resultList) {
                            resultList.add(lindenResult);
                            if (!lindenResult.isSuccess()) {
                                LOGGER.error("Shard [{}] host [{}] failed to get search result : {}", entry.getKey(), hostFuturePair.getKey(), lindenResult.getError());
                            }
                            return BoxedUnit.UNIT;
                        }
                    }

                    @Override
                    public BoxedUnit handle(Throwable t) {
                        LOGGER.error("Shard [{}] host [{}] failed to get search result : {}", entry.getKey(), hostFuturePair.getKey(), Throwables.getStackTraceAsString(t));
                        return BoxedUnit.UNIT;
                    }
                }));
            }
        }
    }
    Future<List<BoxedUnit>> collected = Future.collect(futures);
    try {
        if (clusterFutureAwaitTimeout == 0) {
            Await.result(collected);
        } else {
            Await.result(collected, Duration.apply(clusterFutureAwaitTimeout, TimeUnit.MILLISECONDS));
        }
    } catch (Exception e) {
        LOGGER.error("Failed to get all results, exception: {}", Throwables.getStackTraceAsString(e));
        LOGGER.error(getHostFutureInfo(hosts, futures));
        if (resultList.size() == 0) {
            return new LindenResult().setSuccess(false).setError("Failed to get any shard result, " + Throwables.getStackTraceAsString(e));
        }
    }
    return ResultMerger.merge(request, resultList);
}
Also used : FutureTransformer(com.twitter.util.FutureTransformer) ArrayList(java.util.ArrayList) LindenSearchRequest(com.xiaomi.linden.thrift.common.LindenSearchRequest) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) LindenResult(com.xiaomi.linden.thrift.common.LindenResult) ShardRouteParam(com.xiaomi.linden.thrift.common.ShardRouteParam) Future(com.twitter.util.Future) ArrayList(java.util.ArrayList) List(java.util.List) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Aggregations

Future (com.twitter.util.Future)4 FutureTransformer (com.twitter.util.FutureTransformer)4 IOException (java.io.IOException)4 ArrayList (java.util.ArrayList)4 List (java.util.List)4 Map (java.util.Map)4 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)4 ExecutionException (java.util.concurrent.ExecutionException)4 Response (com.xiaomi.linden.thrift.common.Response)3 ShardRouteParam (com.xiaomi.linden.thrift.common.ShardRouteParam)2 JSONObject (com.alibaba.fastjson.JSONObject)1 LindenIndexRequest (com.xiaomi.linden.thrift.common.LindenIndexRequest)1 LindenResult (com.xiaomi.linden.thrift.common.LindenResult)1 LindenSearchRequest (com.xiaomi.linden.thrift.common.LindenSearchRequest)1