com.spotify.heroic.cluster.ClusterManagerModule.java Source code

Java tutorial

Introduction

Here is the source code for com.spotify.heroic.cluster.ClusterManagerModule.java

Source

/*
 * Copyright (c) 2015 Spotify AB.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.spotify.heroic.cluster;

import static com.spotify.heroic.common.Optionals.pickOptional;
import static java.util.Optional.empty;
import static java.util.Optional.of;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.spotify.heroic.common.ServiceInfo;
import com.spotify.heroic.dagger.PrimaryComponent;
import com.spotify.heroic.lifecycle.LifeCycle;
import com.spotify.heroic.lifecycle.LifeCycleManager;
import com.spotify.heroic.metadata.MetadataComponent;
import com.spotify.heroic.metric.MetricComponent;
import com.spotify.heroic.statistics.HeroicReporter;
import com.spotify.heroic.statistics.QueryReporter;
import com.spotify.heroic.suggest.SuggestComponent;
import dagger.Module;
import dagger.Provides;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import javax.inject.Named;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.tuple.Pair;

/**
 * @author udoprog
 */
@Data
@Module
public class ClusterManagerModule {
    public static final boolean DEFAULT_USE_LOCAL = true;

    private final UUID id;
    private final Map<String, String> tags;
    private final boolean useLocal;
    private final ClusterDiscoveryModule discovery;
    private final List<RpcProtocolModule> protocols;
    private final Set<Map<String, String>> topology;
    private final Optional<NodeMetadataFactory> metadataFactory;

    @Provides
    @ClusterScope
    @Named("local")
    public ClusterNode localClusterNode(LocalClusterNode local) {
        return local;
    }

    @Provides
    @ClusterScope
    public NodeMetadata localMetadata(final ServiceInfo service) {
        return new NodeMetadata(0, id, tags, service);
    }

    @Provides
    @ClusterScope
    public NodeMetadataProvider metadataProvider(final NodeMetadata localMetadata) {
        return metadataFactory.map(fn -> fn.buildProvider(localMetadata))
                .orElseGet(() -> NodeMetadataProvider.staticProvider(localMetadata));
    }

    @Provides
    @ClusterScope
    @Named("useLocal")
    public Boolean useLocal() {
        return useLocal;
    }

    @Provides
    @ClusterScope
    @Named("topology")
    public Set<Map<String, String>> topology() {
        return topology;
    }

    @Provides
    @ClusterScope
    public QueryReporter queryReporter(HeroicReporter heroicReporter) {
        return heroicReporter.newQueryReporter();
    }

    @Provides
    @ClusterScope
    public List<Pair<String, RpcProtocolComponent>> protocolComponents(final NodeMetadataProvider metadataProvider,
            @Named("local") final ClusterNode localClusterNode, final PrimaryComponent primary,
            final MetricComponent metric, final MetadataComponent metadata, final SuggestComponent suggest) {
        final ImmutableList.Builder<Pair<String, RpcProtocolComponent>> protocolComponents = ImmutableList
                .builder();

        /* build up a local component which defines all dependencies for a child component */
        final RpcProtocolModule.Dependencies dependencies = DaggerRpcProtocolModule_Dependencies.builder()
                .primaryComponent(primary).metricComponent(metric).metadataComponent(metadata)
                .suggestComponent(suggest).provided(new RpcProtocolModule.Provided() {
                    @Override
                    public NodeMetadataProvider metadataProvider() {
                        return metadataProvider;
                    }

                    @Override
                    public ClusterNode localClusterNode() {
                        return localClusterNode;
                    }
                }).build();

        for (final RpcProtocolModule m : protocols) {
            protocolComponents.add(Pair.of(m.scheme(), m.module(dependencies)));
        }

        return protocolComponents.build();
    }

    @Provides
    @ClusterScope
    public Map<String, RpcProtocol> protocols(List<Pair<String, RpcProtocolComponent>> protocols) {
        final Map<String, RpcProtocol> map = new HashMap<>();

        for (final Pair<String, RpcProtocolComponent> m : protocols) {
            map.put(m.getLeft(), m.getRight().rpcProtocol());
        }

        return map;
    }

    @Provides
    @ClusterScope
    @Named("cluster")
    LifeCycle clusterLife(LifeCycleManager manager, CoreClusterManager cluster,
            List<Pair<String, RpcProtocolComponent>> protocols) {
        final List<LifeCycle> life = new ArrayList<>();
        life.add(manager.build(cluster));
        protocols.stream().map(p -> p.getRight().life()).forEach(life::add);
        return LifeCycle.combined(life);
    }

    public static Builder builder() {
        return new Builder();
    }

    @AllArgsConstructor(access = AccessLevel.PRIVATE)
    @NoArgsConstructor(access = AccessLevel.PRIVATE)
    public static class Builder {
        private Optional<UUID> id = empty();
        private Optional<Map<String, String>> tags = empty();
        private Optional<Boolean> useLocal = empty();
        private Optional<ClusterDiscoveryModule> discovery = empty();
        private Optional<List<RpcProtocolModule>> protocols = empty();
        private Optional<Set<Map<String, String>>> topology = empty();
        private Optional<NodeMetadataFactory> metadataFactory = empty();

        @JsonCreator
        public Builder(@JsonProperty("id") Optional<UUID> id,
                @JsonProperty("tags") Optional<Map<String, String>> tags,
                @JsonProperty("useLocal") Optional<Boolean> useLocal,
                @JsonProperty("discovery") Optional<ClusterDiscoveryModule> discovery,
                @JsonProperty("protocols") Optional<List<RpcProtocolModule>> protocols,
                @JsonProperty("topology") Optional<Set<Map<String, String>>> topology) {
            this.id = id;
            this.tags = tags;
            this.useLocal = useLocal;
            this.discovery = discovery;
            this.protocols = protocols;
            this.topology = topology;
        }

        public Builder id(UUID id) {
            this.id = of(id);
            return this;
        }

        public Builder tags(Map<String, String> tags) {
            this.tags = of(tags);
            return this;
        }

        public Builder useLocal(Boolean useLocal) {
            this.useLocal = of(useLocal);
            return this;
        }

        public Builder discovery(ClusterDiscoveryModule discovery) {
            this.discovery = of(discovery);
            return this;
        }

        public Builder protocols(List<RpcProtocolModule> protocols) {
            this.protocols = of(protocols);
            return this;
        }

        public Builder topology(Set<Map<String, String>> topology) {
            this.topology = of(topology);
            return this;
        }

        /**
         * Set the metadata factory.
         *
         * Only used for testing purposes.
         *
         * @param metadataFactory factory to use
         * @return this builder
         */
        public Builder metadataFactory(NodeMetadataFactory metadataFactory) {
            this.metadataFactory = of(metadataFactory);
            return this;
        }

        public Builder merge(Builder o) {
            // @formatter:off
            return new Builder(pickOptional(id, o.id), pickOptional(tags, o.tags),
                    pickOptional(useLocal, o.useLocal), pickOptional(discovery, o.discovery),
                    pickOptional(protocols, o.protocols), pickOptional(topology, o.topology),
                    pickOptional(metadataFactory, o.metadataFactory));
            // @formatter:on
        }

        public ClusterManagerModule build() {
            // @formatter:off
            return new ClusterManagerModule(id.orElseGet(UUID::randomUUID), tags.orElseGet(ImmutableMap::of),
                    useLocal.orElse(DEFAULT_USE_LOCAL), discovery.orElseGet(ClusterDiscoveryModule::nullModule),
                    protocols.orElseGet(ImmutableList::of), topology.orElseGet(ImmutableSet::of), metadataFactory);
            // @formatter:on
        }
    }
}