All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.scheduledexecutor.impl.InvokeOnMembers Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * Copyright (c) 2008-2023, Hazelcast, Inc. All Rights Reserved.
 *
 * 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,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hazelcast.scheduledexecutor.impl;

import com.hazelcast.cluster.Member;
import com.hazelcast.logging.ILogger;
import com.hazelcast.spi.impl.NodeEngine;
import com.hazelcast.spi.impl.operationservice.Operation;
import com.hazelcast.spi.impl.operationservice.OperationService;
import com.hazelcast.spi.annotation.PrivateApi;
import com.hazelcast.internal.serialization.SerializationService;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.function.Supplier;

/**
 * Executes an operation on a set of targets. Similar to {@link com.hazelcast.spi.impl.operationservice.impl.InvokeOnPartitions}
 * but for members.
 */
@PrivateApi
public final class InvokeOnMembers {

    private static final int TRY_COUNT = 10;
    private static final int TRY_PAUSE_MILLIS = 300;

    private final ILogger logger;

    private final OperationService operationService;
    private final SerializationService serializationService;

    private final String serviceName;
    private final Supplier operationFactory;
    private final Collection targets;
    private final Map futures;
    private final Map results;

    public InvokeOnMembers(NodeEngine nodeEngine, String serviceName, Supplier operationFactory,
                           Collection targets) {
        this.logger = nodeEngine.getLogger(getClass());
        this.operationService = nodeEngine.getOperationService();
        this.serializationService = nodeEngine.getSerializationService();
        this.serviceName = serviceName;
        this.operationFactory = operationFactory;
        this.targets = targets;
        this.futures = new HashMap(targets.size());
        this.results = new HashMap(targets.size());
    }

    /**
     * Executes the operation on all targets.
     */
    public Map invoke()
            throws Exception {
        invokeOnAllTargets();

        awaitCompletion();

        retryFailedTargets();

        return results;
    }

    private void invokeOnAllTargets() {
        for (Member target : targets) {
            Future future = operationService.createInvocationBuilder(serviceName, operationFactory.get(), target.getAddress())
                                            .setTryCount(TRY_COUNT).setTryPauseMillis(TRY_PAUSE_MILLIS).invoke();
            futures.put(target, future);
        }
    }

    private void awaitCompletion() {
        for (Map.Entry responseEntry : futures.entrySet()) {
            try {
                Future future = responseEntry.getValue();
                results.put(responseEntry.getKey(), serializationService.toObject(future.get()));
            } catch (Throwable t) {
                if (logger.isFinestEnabled()) {
                    logger.finest(t);
                } else {
                    logger.warning(t.getMessage());
                }

                results.put(responseEntry.getKey(), t);
            }
        }
    }

    private void retryFailedTargets()
            throws InterruptedException, ExecutionException {
        List failedMembers = new LinkedList();
        for (Map.Entry memberResult : results.entrySet()) {
            Member member = memberResult.getKey();
            Object result = memberResult.getValue();
            if (result instanceof Throwable) {
                failedMembers.add(member);
            }
        }

        for (Member failedMember : failedMembers) {
            Operation operation = operationFactory.get();
            Future future = operationService.createInvocationBuilder(serviceName, operation, failedMember.getAddress()).invoke();
            results.put(failedMember, future);
        }

        for (Member failedMember : failedMembers) {
            Future future = (Future) results.get(failedMember);
            Object result = future.get();
            results.put(failedMember, result);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy