Skip to content

Commit

Permalink
Refactoring everything at BlockNodeApp to use Dagger singletons inste…
Browse files Browse the repository at this point in the history
…ad injected at the constructor by DaggerComponent, instead of initializing them on the startup sequence. Also, adding a BlockNodeApp Test now that everything is being injected.

Signed-off-by: Alfredo Gutierrez <[email protected]>
  • Loading branch information
AlfredoG87 committed Aug 24, 2024
1 parent cedb64d commit 31eddb9
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 56 deletions.
62 changes: 8 additions & 54 deletions server/src/main/java/com/hedera/block/server/BlockNodeApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,10 @@
import static java.lang.System.Logger;
import static java.lang.System.Logger.Level.INFO;

import com.hedera.block.server.config.BlockNodeContext;
import com.hedera.block.server.data.ObjectEvent;
import com.hedera.block.server.health.HealthService;
import com.hedera.block.server.mediator.LiveStreamMediatorBuilder;
import com.hedera.block.server.mediator.StreamMediator;
import com.hedera.block.server.persistence.storage.PersistenceStorageConfig;
import com.hedera.block.server.persistence.storage.read.BlockAsDirReaderBuilder;
import com.hedera.block.server.persistence.storage.read.BlockReader;
import com.hedera.block.server.persistence.storage.write.BlockWriter;
import com.hedera.hapi.block.SubscribeStreamResponse;
import com.hedera.hapi.block.stream.Block;
import com.hedera.hapi.block.stream.BlockItem;
import edu.umd.cs.findbugs.annotations.NonNull;
import io.helidon.webserver.WebServer;
import io.helidon.webserver.WebServerConfig;
import io.helidon.webserver.grpc.GrpcRouting;
import io.helidon.webserver.http.HttpRouting;
import java.io.IOException;
Expand All @@ -50,27 +40,25 @@ public class BlockNodeApp {

private final ServiceStatus serviceStatus;
private final HealthService healthService;
private final BlockNodeContext blockNodeContext;
private final BlockWriter<BlockItem> blockWriter;
private final BlockStreamService blockStreamService;
private final WebServerConfig.Builder webServerBuilder;

/**
* Has all needed dependencies to start the server and initialize the context.
*
* @param serviceStatus the status of the service
* @param healthService the health service
* @param blockNodeContext the context of the block node
* @param blockWriter the block writer
*/
@Inject
public BlockNodeApp(
@NonNull ServiceStatus serviceStatus,
@NonNull HealthService healthService,
@NonNull BlockNodeContext blockNodeContext,
BlockWriter<BlockItem> blockWriter) {
@NonNull BlockStreamService blockStreamService,
@NonNull WebServerConfig.Builder webServerBuilder) {
this.serviceStatus = serviceStatus;
this.healthService = healthService;
this.blockNodeContext = blockNodeContext;
this.blockWriter = blockWriter;
this.blockStreamService = blockStreamService;
this.webServerBuilder = webServerBuilder;
}

/**
Expand All @@ -80,24 +68,6 @@ public BlockNodeApp(
*/
public void start() throws IOException {

// final BlockWriter<BlockItem> blockWriter =
// BlockAsDirWriterBuilder.newBuilder(blockNodeContext).build();

final StreamMediator<BlockItem, ObjectEvent<SubscribeStreamResponse>> streamMediator =
LiveStreamMediatorBuilder.newBuilder(blockWriter, blockNodeContext, serviceStatus)
.build();

final BlockReader<Block> blockReader =
BlockAsDirReaderBuilder.newBuilder(
blockNodeContext
.configuration()
.getConfigData(PersistenceStorageConfig.class))
.build();

final BlockStreamService blockStreamService =
buildBlockStreamService(
streamMediator, blockReader, serviceStatus, blockNodeContext);

final GrpcRouting.Builder grpcRouting = GrpcRouting.builder().service(blockStreamService);

final HttpRouting.Builder httpRouting =
Expand All @@ -106,11 +76,7 @@ public void start() throws IOException {
// Build the web server
// TODO: make port server a configurable value.
final WebServer webServer =
WebServer.builder()
.port(8080)
.addRouting(grpcRouting)
.addRouting(httpRouting)
.build();
webServerBuilder.port(8080).addRouting(grpcRouting).addRouting(httpRouting).build();

// Update the serviceStatus with the web server
serviceStatus.setWebServer(webServer);
Expand All @@ -121,16 +87,4 @@ public void start() throws IOException {
// Log the server status
LOGGER.log(INFO, String.format("Block Node Server started at port: %d", webServer.port()));
}

@NonNull
private static BlockStreamService buildBlockStreamService(
@NonNull
final StreamMediator<BlockItem, ObjectEvent<SubscribeStreamResponse>>
streamMediator,
@NonNull final BlockReader<Block> blockReader,
@NonNull final ServiceStatus serviceStatus,
@NonNull final BlockNodeContext blockNodeContext) {

return new BlockStreamService(streamMediator, blockReader, serviceStatus, blockNodeContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

package com.hedera.block.server;

import com.hedera.block.server.config.ConfigInjectionModule;
import com.hedera.block.server.health.HealthInjectionModule;
import com.hedera.block.server.mediator.MediatorInjectionModule;
import com.hedera.block.server.persistence.storage.PersistenceInjectionModule;
import dagger.Component;
import javax.inject.Singleton;
Expand All @@ -27,7 +29,9 @@
modules = {
BlockNodeAppInjectionModule.class,
HealthInjectionModule.class,
PersistenceInjectionModule.class
PersistenceInjectionModule.class,
MediatorInjectionModule.class,
ConfigInjectionModule.class
})
public interface BlockNodeAppInjectionComponent {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,17 @@

import com.hedera.block.server.config.BlockNodeContext;
import com.hedera.block.server.config.BlockNodeContextFactory;
import com.hedera.block.server.data.ObjectEvent;
import com.hedera.block.server.mediator.StreamMediator;
import com.hedera.block.server.persistence.storage.read.BlockReader;
import com.hedera.hapi.block.SubscribeStreamResponse;
import com.hedera.hapi.block.stream.Block;
import com.hedera.hapi.block.stream.BlockItem;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import edu.umd.cs.findbugs.annotations.NonNull;
import io.helidon.webserver.WebServerConfig;
import java.io.IOException;
import javax.inject.Singleton;

Expand All @@ -46,13 +54,31 @@ public interface BlockNodeAppInjectionModule {
*
* @return a block node context singleton
*/
@Provides
@Singleton
@Provides
static BlockNodeContext provideBlockNodeContext() {
try {
return BlockNodeContextFactory.create();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Singleton
@Provides
static BlockStreamService provideBlockStreamService(
@NonNull
final StreamMediator<BlockItem, ObjectEvent<SubscribeStreamResponse>>
streamMediator,
@NonNull final BlockReader<Block> blockReader,
@NonNull final ServiceStatus serviceStatus,
@NonNull final BlockNodeContext blockNodeContext) {
return new BlockStreamService(streamMediator, blockReader, serviceStatus, blockNodeContext);
}

@Singleton
@Provides
static WebServerConfig.Builder provideWebServerConfigBuilder() {
return WebServerConfig.builder();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import java.io.IOException;
import java.time.Clock;
import java.util.Optional;
import javax.inject.Inject;

/**
* The BlockStreamService class defines the gRPC service for the block stream service. It provides
Expand All @@ -76,6 +77,7 @@ public class BlockStreamService implements GrpcService {
* @param serviceStatus the service status provides methods to check service availability and to
* stop the service and web server in the event of an unrecoverable exception
*/
@Inject
BlockStreamService(
@NonNull
final StreamMediator<BlockItem, ObjectEvent<SubscribeStreamResponse>>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (C) 2024 Hedera Hashgraph, LLC
*
* 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.hedera.block.server.config;

import com.hedera.block.server.consumer.ConsumerConfig;
import com.hedera.block.server.persistence.storage.PersistenceStorageConfig;
import com.swirlds.common.config.BasicCommonConfig;
import com.swirlds.common.metrics.config.MetricsConfig;
import com.swirlds.common.metrics.platform.prometheus.PrometheusConfig;
import com.swirlds.config.api.Configuration;
import com.swirlds.config.api.ConfigurationBuilder;
import com.swirlds.config.extensions.sources.ClasspathFileConfigSource;
import com.swirlds.config.extensions.sources.SystemEnvironmentConfigSource;
import com.swirlds.config.extensions.sources.SystemPropertiesConfigSource;
import dagger.Module;
import dagger.Provides;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.io.IOException;
import java.nio.file.Path;
import javax.inject.Singleton;

@Module
public interface ConfigInjectionModule {

static final String APPLICATION_PROPERTIES = "app.properties";

@Singleton
@Provides
static Configuration provideConfiguration() {
try {
return ConfigurationBuilder.create()
.withSource(SystemEnvironmentConfigSource.getInstance())
.withSource(SystemPropertiesConfigSource.getInstance())
.withSource(new ClasspathFileConfigSource(Path.of(APPLICATION_PROPERTIES)))
.autoDiscoverExtensions()
.build();
} catch (IOException e) {
throw new RuntimeException("Failed to create configuration", e);
}
}

@Singleton
@Provides
static PersistenceStorageConfig providePersistenceStorageConfig(
@NonNull Configuration configuration) {
return configuration.getConfigData(PersistenceStorageConfig.class);
}

@Singleton
@Provides
static MetricsConfig provideMetricsConfig(@NonNull Configuration configuration) {
return configuration.getConfigData(MetricsConfig.class);
}

@Singleton
@Provides
static PrometheusConfig providePrometheusConfig(@NonNull Configuration configuration) {
return configuration.getConfigData(PrometheusConfig.class);
}

@Singleton
@Provides
static ConsumerConfig provideConsumerConfig(@NonNull Configuration configuration) {
return configuration.getConfigData(ConsumerConfig.class);
}

@Singleton
@Provides
static BasicCommonConfig provideBasicCommonConfig(@NonNull Configuration configuration) {
return configuration.getConfigData(BasicCommonConfig.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2024 Hedera Hashgraph, LLC
*
* 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.hedera.block.server.mediator;

import com.hedera.block.server.ServiceStatus;
import com.hedera.block.server.config.BlockNodeContext;
import com.hedera.block.server.data.ObjectEvent;
import com.hedera.block.server.persistence.storage.write.BlockWriter;
import com.hedera.hapi.block.SubscribeStreamResponse;
import com.hedera.hapi.block.stream.BlockItem;
import dagger.Module;
import dagger.Provides;
import edu.umd.cs.findbugs.annotations.NonNull;
import javax.inject.Singleton;

/** A Dagger module for providing dependencies for Mediator Module.` */
@Module
public interface MediatorInjectionModule {

/**
* Provides the stream mediator.
*
* @param blockWriter the block writer
* @param blockNodeContext the block node context
* @param serviceStatus the service status
* @return the stream mediator
*/
@Provides
@Singleton
static StreamMediator<BlockItem, ObjectEvent<SubscribeStreamResponse>> providesStreamMediator(
@NonNull BlockWriter<BlockItem> blockWriter,
@NonNull BlockNodeContext blockNodeContext,
@NonNull ServiceStatus serviceStatus) {
return LiveStreamMediatorBuilder.newBuilder(blockWriter, blockNodeContext, serviceStatus)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
package com.hedera.block.server.persistence.storage;

import com.hedera.block.server.config.BlockNodeContext;
import com.hedera.block.server.persistence.storage.read.BlockAsDirReaderBuilder;
import com.hedera.block.server.persistence.storage.read.BlockReader;
import com.hedera.block.server.persistence.storage.write.BlockAsDirWriterBuilder;
import com.hedera.block.server.persistence.storage.write.BlockWriter;
import com.hedera.hapi.block.stream.Block;
import com.hedera.hapi.block.stream.BlockItem;
import dagger.Module;
import dagger.Provides;
Expand All @@ -45,4 +48,10 @@ static BlockWriter<BlockItem> providesBlockWriter(@NonNull BlockNodeContext bloc
throw new RuntimeException("Failed to create block writer", e);
}
}

@Provides
@Singleton
static BlockReader<Block> providesBlockReader(@NonNull PersistenceStorageConfig config) {
return BlockAsDirReaderBuilder.newBuilder(config).build();
}
}
Loading

0 comments on commit 31eddb9

Please sign in to comment.