/*
* 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.rpc.grpc;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.spotify.heroic.cluster.RpcProtocolComponent;
import com.spotify.heroic.cluster.RpcProtocolModule;
import com.spotify.heroic.lifecycle.LifeCycle;
import com.spotify.heroic.lifecycle.LifeCycleManager;
import dagger.Component;
import dagger.Module;
import dagger.Provides;
import eu.toolchain.async.AsyncFramework;
import eu.toolchain.async.ResolvableFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import javax.inject.Named;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Data
public class GrpcRpcProtocolModule implements RpcProtocolModule {
private static final Object PARENT = new Object();
private static final String DEFAULT_HOST = "0.0.0.0";
private static final int DEFAULT_PORT = 9698;
private static final int DEFAULT_PARENT_THREADS = 2;
private static final int DEFAULT_CHILD_THREADS = 100;
private static final int DEFAULT_MAX_FRAME_SIZE = 10 * 1000000;
private static final long DEFAULT_SEND_TIMEOUT = 5000;
private final InetSocketAddress address;
private final int parentThreads;
private final int childThreads;
private final int maxFrameSize;
@JsonCreator
public GrpcRpcProtocolModule(
@JsonProperty("host") String host, @JsonProperty("port") Integer port,
@JsonProperty("parentThreads") Integer parentThreads,
@JsonProperty("childThreads") Integer childThreads,
@JsonProperty("maxFrameSize") Integer maxFrameSize
) {
this.address = new InetSocketAddress(Optional.ofNullable(host).orElse(DEFAULT_HOST),
Optional.ofNullable(port).orElse(DEFAULT_PORT));
this.parentThreads = Optional.ofNullable(parentThreads).orElse(DEFAULT_PARENT_THREADS);
this.childThreads = Optional.ofNullable(childThreads).orElse(DEFAULT_CHILD_THREADS);
this.maxFrameSize = Optional.ofNullable(maxFrameSize).orElse(DEFAULT_MAX_FRAME_SIZE);
}
@Override
public RpcProtocolComponent module(final Dependencies dependencies) {
return DaggerGrpcRpcProtocolModule_C
.builder()
.dependencies(dependencies)
.m(new M())
.build();
}
@GrpcRpcScope
@Component(modules = M.class, dependencies = Dependencies.class)
interface C extends RpcProtocolComponent {
@Override
GrpcRpcProtocol rpcProtocol();
@Override
LifeCycle life();
}
@RequiredArgsConstructor
@Module
class M {
@Provides
@GrpcRpcScope
@Named("bindFuture")
ResolvableFuture<InetSocketAddress> bindFuture(final AsyncFramework async) {
return async.future();
}
@Provides
@GrpcRpcScope
@Named("grpcBindAddress")
InetSocketAddress grpcBindAddress() {
return address;
}
@Provides
@GrpcRpcScope
@Named("defaultPort")
int defaultPort() {
return DEFAULT_PORT;
}
@Provides
@GrpcRpcScope
@Named("maxFrameSize")
int maxFrameSize() {
return maxFrameSize;
}
@Provides
@GrpcRpcScope
@Named("boss")
NioEventLoopGroup boss() {
return new NioEventLoopGroup(4);
}
@Provides
@GrpcRpcScope
@Named("worker")
NioEventLoopGroup worker() {
return new NioEventLoopGroup(Runtime.getRuntime().availableProcessors() * 4);
}
@Provides
@GrpcRpcScope
LifeCycle server(
LifeCycleManager manager, GrpcRpcProtocolServer server
) {
final List<LifeCycle> life = new ArrayList<>();
life.add(manager.build(server));
return LifeCycle.combined(life);
}
}
@Override
public String scheme() {
return "grpc";
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String host = DEFAULT_HOST;
private int port = DEFAULT_PORT;
private int parentThreads = DEFAULT_PARENT_THREADS;
private int childThreads = DEFAULT_CHILD_THREADS;
private int maxFrameSize = DEFAULT_MAX_FRAME_SIZE;
public Builder host(final String host) {
this.host = host;
return this;
}
public Builder port(final int port) {
this.port = port;
return this;
}
public Builder parentThreads(final int parentThreads) {
this.parentThreads = parentThreads;
return this;
}
public Builder childThreads(final int childThreads) {
this.childThreads = childThreads;
return this;
}
public Builder maxFrameSize(final int maxFrameSize) {
this.maxFrameSize = maxFrameSize;
return this;
}
public GrpcRpcProtocolModule build() {
return new GrpcRpcProtocolModule(host, port, parentThreads, childThreads, maxFrameSize);
}
}
}