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

io.appform.ranger.client.AbstractRangerHubClient Maven / Gradle / Ivy

There is a newer version: 1.1-RC5
Show newest version
/*
 * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd.
 *
 * 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 io.appform.ranger.client;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Preconditions;
import io.appform.ranger.client.utils.CriteriaUtils;
import io.appform.ranger.core.finderhub.ServiceDataSource;
import io.appform.ranger.core.finderhub.ServiceFinderFactory;
import io.appform.ranger.core.finderhub.ServiceFinderHub;
import io.appform.ranger.core.model.*;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import io.appform.ranger.core.util.FinderUtils;
import lombok.Getter;
import lombok.experimental.SuperBuilder;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Getter
@SuperBuilder
public abstract class AbstractRangerHubClient, D extends Deserializer> implements RangerHubClient {

    private final String namespace;
    private final ObjectMapper mapper;
    private final D deserializer;
    private final Predicate initialCriteria;
    private final boolean alwaysUseInitialCriteria;
    private int nodeRefreshTimeMs;
    private ServiceFinderHub hub;
    private ServiceDataSource serviceDataSource;

    /**
     * Initial time to wait for service node data to be refreshed in service registry (in milliseconds)
     */
    private long serviceRefreshTimeoutMs;

    /**
     * Time to wait for Hub Start completion (in milliseconds)
     * Hub Start is considered to be completed if service registry for all eligible services has been refreshed
     */
    private long hubStartTimeoutMs;
    private Set excludedServices;

    @Override
    public void start() {
        Preconditions.checkNotNull(mapper, "Mapper can't be null");
        Preconditions.checkNotNull(namespace, "namespace can't be null");
        Preconditions.checkNotNull(deserializer, "deserializer can't be null");

        if (this.nodeRefreshTimeMs < HubConstants.MINIMUM_REFRESH_TIME_MS) {
            log.warn("Node info update interval too low: {} ms. Has been upgraded to {} ms ",
                     this.nodeRefreshTimeMs,
                    HubConstants.MINIMUM_REFRESH_TIME_MS);
        }
        this.nodeRefreshTimeMs = Math.max(HubConstants.MINIMUM_REFRESH_TIME_MS, this.nodeRefreshTimeMs);

        if (this.serviceRefreshTimeoutMs <= 0) {
            log.warn("Service Refresh interval too low: {} ms. Has been upgraded to {} ms ",
                    this.serviceRefreshTimeoutMs,
                    HubConstants.SERVICE_REFRESH_TIMEOUT_MS);
            this.serviceRefreshTimeoutMs = HubConstants.SERVICE_REFRESH_TIMEOUT_MS;
        }

        if (this.hubStartTimeoutMs <= 0) {
            log.warn("Hub Refresh interval too low: {} ms. Has been upgraded to {} ms ",
                    this.hubStartTimeoutMs,
                    HubConstants.HUB_START_TIMEOUT_MS);
            this.hubStartTimeoutMs = HubConstants.HUB_START_TIMEOUT_MS;
        }

        this.excludedServices = Objects.requireNonNullElseGet(this.excludedServices, Set::of);

        if(null == this.serviceDataSource){
            this.serviceDataSource = getDefaultDataSource();
        }

        this.hub = buildHub();
        this.hub.start();
    }

    @Override
    public void stop() {
        if (null != hub) {
            hub.stop();
        }
    }

    @Override
    public Optional> getNode(final Service service) {
        return getNode(service, initialCriteria);
    }

    @Override
    public List> getAllNodes(final Service service) {
        return getAllNodes(service, initialCriteria);
    }

    @Override
    public Optional> getNode(final Service service, final Predicate criteria) {
        return this.getNode(service, criteria, null);
    }

    @Override
    public Optional> getNode(
            final Service service,
            final Predicate criteria,
            final ShardSelector shardSelector) {
        return getNode(service, criteria, shardSelector, null);
    }

    @Override
    public Optional> getNode(
            final Service service,
            final Predicate criteria,
            final ShardSelector shardSelector,
            final ServiceNodeSelector nodeSelector) {
        return this.getHub()
                .finder(service)
                .flatMap(trServiceFinder
                                 -> trServiceFinder.get(CriteriaUtils.getCriteria(alwaysUseInitialCriteria,
                                                                                  initialCriteria,
                                                                                  criteria),
                                                        shardSelector,
                                                        nodeSelector));
    }

    @Override
    public List> getAllNodes(
            final Service service,
            final Predicate criteria
                                           ) {
        return getAllNodes(service, criteria, null);
    }

    @Override
    public List> getAllNodes(
            final Service service,
            final Predicate criteria,
            final ShardSelector shardSelector) {
        return this.getHub()
                .finder(service)
                .map(trServiceFinder -> trServiceFinder.getAll(
                        CriteriaUtils.getCriteria(alwaysUseInitialCriteria, initialCriteria, criteria),
                        shardSelector))
                .orElse(Collections.emptyList());
    }

    @Override
    public Collection getRegisteredServices() {
        try {
            return FinderUtils.getEligibleServices(this.getHub().getServiceDataSource().services(), excludedServices);
        }
        catch (Exception e) {
            log.error("Call to the hub failed with exception, {}", e.getMessage());
            return Collections.emptySet();
        }
    }

    /**
     * Tries to dynamically add service for discovery.
     * Method will return asynchronously after adding service to ServiceDataSource.
     * To block till rangerHub is ready to discover service wait for future completion
     *
     * @throws UnsupportedOperationException for any datasource which doesnt support
     *          dynamic addition of services
     * @throws IllegalStateException if called before hub is started
     *
     * @return CompletableFuture which waits for hub to be ready for discovering the new service
     */
    @Override
    public CompletableFuture addService(Service service) {
        if(hub == null) {
            throw new IllegalStateException("Hub not started yet. Call .start()");
        }
        return hub.buildFinder(service);
    }


    protected abstract ServiceDataSource getDefaultDataSource();

    protected abstract ServiceFinderFactory getFinderFactory();

    protected abstract ServiceFinderHub buildHub();

}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy