Skip to content

Commit

Permalink
Merge branch 'main' into improve-android-example
Browse files Browse the repository at this point in the history
  • Loading branch information
dikel authored Oct 24, 2022
2 parents 5ba41f7 + b0fde37 commit 6226a5f
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 30 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `CustomFee.[set|get]AllCollectorsAreExempt()`
- The Android example can now be run with the local SDK version

### Fixed
- Execute with a timeout can ignore timeout and block indefinitely in CI tests

## 2.17.4

### Added
Expand Down
2 changes: 1 addition & 1 deletion examples/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ dependencies {

implementation "com.google.code.gson:gson:2.9.1"
implementation "org.slf4j:slf4j-simple:2.0.3"
implementation "io.grpc:grpc-netty-shaded:1.49.1"
implementation "io.grpc:grpc-netty-shaded:1.50.2"
implementation "io.github.cdimascio:java-dotenv:5.3.1"
implementation "com.google.errorprone:error_prone_core:2.15.0"
}
Expand Down
22 changes: 11 additions & 11 deletions sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugins {
id "idea"
id "signing"
id "maven-publish"
id "com.google.protobuf" version "0.8.19"
id "com.google.protobuf" version "0.9.1"
id "com.github.spotbugs" version "5.0.12"
}

Expand All @@ -29,22 +29,22 @@ task javadocJar(type: Jar) {

dependencies {
// https://github.com/bsideup/jabel
annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:0.4.2'
annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0'

// https://mvnrepository.com/artifact/com.github.spotbugs/spotbugs-annotations
implementation group: 'com.github.spotbugs', name: 'spotbugs-annotations', version: '4.7.2'

// https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15to18
implementation group: 'org.bouncycastle', name: 'bcprov-jdk15to18', version: '1.71'
implementation group: 'org.bouncycastle', name: 'bcprov-jdk15to18', version: '1.72'

// https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15to18
implementation group: 'org.bouncycastle', name: 'bcpkix-jdk15to18', version: '1.71'
implementation group: 'org.bouncycastle', name: 'bcpkix-jdk15to18', version: '1.72'

// https://mvnrepository.com/artifact/org.slf4j/slf4j-api
implementation 'org.slf4j:slf4j-api:2.0.3'

implementation "io.grpc:grpc-core:1.49.1"
implementation "io.grpc:grpc-stub:1.49.1"
implementation "io.grpc:grpc-core:1.50.2"
implementation "io.grpc:grpc-stub:1.50.2"

implementation "com.google.code.gson:gson:2.9.1"
implementation 'javax.annotation:javax.annotation-api:1.3.2'
Expand All @@ -53,24 +53,24 @@ dependencies {
testImplementation "org.assertj:assertj-core:3.23.1"
testImplementation "io.github.json-snapshot:json-snapshot:1.0.17"
testImplementation "org.junit.jupiter:junit-jupiter-engine:5.9.1"
testImplementation "org.junit.jupiter:junit-jupiter-params:5.9.0"
testImplementation "org.junit.jupiter:junit-jupiter-params:5.9.1"

testRuntimeOnly "org.slf4j:slf4j-simple:2.0.3"
testRuntimeOnly "io.grpc:grpc-netty-shaded:1.49.1"
testRuntimeOnly "io.grpc:grpc-netty-shaded:1.50.2"
testRuntimeOnly 'org.slf4j:slf4j-nop:2.0.3'

integrationTestRuntimeOnly 'io.grpc:grpc-netty-shaded:1.49.1'
integrationTestRuntimeOnly 'io.grpc:grpc-netty-shaded:1.50.2'
integrationTestRuntimeOnly 'org.slf4j:slf4j-nop:2.0.2'
}

// https://github.com/google/protobuf-gradle-plugin
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.21.6"
artifact = "com.google.protobuf:protoc:3.21.7"
}
plugins {
grpc {
artifact = "io.grpc:protoc-gen-grpc-java:1.49.1"
artifact = "io.grpc:protoc-gen-grpc-java:1.50.2"
}
}
}
Expand Down
30 changes: 24 additions & 6 deletions sdk/src/main/java/com/hedera/hashgraph/sdk/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
package com.hedera.hashgraph.sdk;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java8.util.Lists;
import java8.util.concurrent.CompletableFuture;
import java8.util.concurrent.CompletionStage;
import java8.util.function.BiConsumer;
Expand All @@ -48,10 +48,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.*;
import java.util.function.Supplier;

import static com.hedera.hashgraph.sdk.BaseNodeAddress.PORT_NODE_PLAIN;
Expand Down Expand Up @@ -137,7 +134,14 @@ public final class Client implements AutoCloseable {
* @return the executor service
*/
static ExecutorService createExecutor() {
return ForkJoinPool.commonPool();
var threadFactory = new ThreadFactoryBuilder()
.setNameFormat("hedera-sdk-%d")
.setDaemon(true)
.build();

return Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors(),
threadFactory);
}

/**
Expand Down Expand Up @@ -1289,6 +1293,20 @@ public synchronized void close(Duration timeout) throws TimeoutException {
var networkError = network.awaitClose(closeDeadline, null);
var mirrorNetworkError = mirrorNetwork.awaitClose(closeDeadline, networkError);

// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html
try {
executor.shutdown();
if (!executor.awaitTermination(timeout.getSeconds() / 2, TimeUnit.SECONDS)) {
executor.shutdownNow();
if (!executor.awaitTermination(timeout.getSeconds() / 2, TimeUnit.SECONDS)) {
logger.warn("Pool did not terminate");
}
}
} catch (InterruptedException ex) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}

if (mirrorNetworkError != null) {
if (mirrorNetworkError instanceof TimeoutException) {
throw (TimeoutException) mirrorNetworkError;
Expand Down
68 changes: 56 additions & 12 deletions sdk/src/test/java/com/hedera/hashgraph/sdk/ClientCloseTest.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
package com.hedera.hashgraph.sdk;

import org.bouncycastle.asn1.x509.Time;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockSettings;
import org.threeten.bp.Duration;

import java.util.Collections;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.*;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatException;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.in;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.*;

public class ClientCloseTest {
@Test
Expand Down Expand Up @@ -70,4 +61,57 @@ void closeHandlesMirrorNetworkInterrupted() {
assertThatExceptionOfType(RuntimeException.class).isThrownBy(client::close).withCause(interruptedException);
assertThat(network.hasShutDownNow).isFalse();
}

@Test
void closeHandlesExecutorShutdown() throws TimeoutException {
var executor = Client.createExecutor();
var network = Network.forNetwork(executor, Collections.emptyMap());
var mirrorNetwork = MirrorNetwork.forNetwork(executor, Collections.emptyList());
var client = new Client(executor, network, mirrorNetwork, null, null);

client.close();
assertThat(executor.isShutdown()).isTrue();
}

@Test
void closeHandlesExecutorTerminatingInTime() throws InterruptedException, TimeoutException {
var duration = Duration.ofSeconds(30);
var executor = mock(ThreadPoolExecutor.class);
var network = Network.forNetwork(executor, Collections.emptyMap());
var mirrorNetwork = MirrorNetwork.forNetwork(executor, Collections.emptyList());
var client = new Client(executor, network, mirrorNetwork, null, null);

doReturn(true).when(executor).awaitTermination(30 / 2, TimeUnit.SECONDS);

client.close(duration);
verify(executor, times(0)).shutdownNow();
}

@Test
void closeHandlesExecutorNotTerminatingInTime() throws InterruptedException, TimeoutException {
var duration = Duration.ofSeconds(30);
var executor = mock(ThreadPoolExecutor.class);
var network = Network.forNetwork(executor, Collections.emptyMap());
var mirrorNetwork = MirrorNetwork.forNetwork(executor, Collections.emptyList());
var client = new Client(executor, network, mirrorNetwork, null, null);

doReturn(false).when(executor).awaitTermination(30 / 2, TimeUnit.SECONDS);

client.close(duration);
verify(executor, times(1)).shutdownNow();
}

@Test
void closeHandlesExecutorWhenThreadIsInterrupted() throws InterruptedException, TimeoutException {
var duration = Duration.ofSeconds(30);
var executor = mock(ThreadPoolExecutor.class);
var network = Network.forNetwork(executor, Collections.emptyMap());
var mirrorNetwork = MirrorNetwork.forNetwork(executor, Collections.emptyList());
var client = new Client(executor, network, mirrorNetwork, null, null);

doThrow(new InterruptedException()).when(executor).awaitTermination(30 / 2, TimeUnit.SECONDS);

client.close(duration);
verify(executor, times(1)).shutdownNow();
}
}

0 comments on commit 6226a5f

Please sign in to comment.