Update to Neo4j 4.0.0 driver, add more information to health check.

This commit is contained in:
Michael Simons
2019-12-11 13:46:48 +01:00
committed by Guillaume Smet
parent 1e9a60d45f
commit 366ed325b7
6 changed files with 86 additions and 39 deletions

View File

@@ -148,7 +148,7 @@
<jgit.version>5.5.1.201910021850-r</jgit.version>
<flyway.version>6.1.1</flyway.version>
<yasson.version>1.0.5</yasson.version>
<neo4j-java-driver.version>4.0.0-beta03</neo4j-java-driver.version>
<neo4j-java-driver.version>4.0.0</neo4j-java-driver.version>
<mongo-client.version>3.10.2</mongo-client.version>
<mongo-reactivestreams-client.version>1.11.0</mongo-reactivestreams-client.version>
<artemis.version>2.10.1</artemis.version>

View File

@@ -4,7 +4,7 @@ and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
////
= Quarkus - Neo4j
:neo4j_version: 3.5.6
:neo4j_version: 3.5.13
include::./attributes.adoc[]
:extension-status: preview
@@ -429,7 +429,7 @@ Please add the following dependency management and dependency to your `pom.xml`
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-bom</artifactId>
<version>Californium-SR4</version>
<version>Dysprosium-RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -460,7 +460,7 @@ import javax.ws.rs.core.MediaType;
import org.neo4j.driver.Driver;
import org.neo4j.driver.reactive.RxSession;
import org.neo4j.driver.reactive.RxStatementResult;
import org.neo4j.driver.reactive.RxResult;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
@@ -477,7 +477,7 @@ public class ReactiveFruitResource {
@Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> get() {
return Flux.using(driver::rxSession, session -> session.readTransaction(tx -> {
RxStatementResult result = tx.run("MATCH (f:Fruit) RETURN f.name as name ORDER BY f.name");
RxResult result = tx.run("MATCH (f:Fruit) RETURN f.name as name ORDER BY f.name");
return Flux.from(result.records()).map(record -> record.get("name").asString());
}), RxSession::close);
}

View File

@@ -7,22 +7,89 @@ import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.HealthCheckResponseBuilder;
import org.eclipse.microprofile.health.Readiness;
import org.jboss.logging.Logger;
import org.neo4j.driver.AccessMode;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Session;
import org.neo4j.driver.SessionConfig;
import org.neo4j.driver.exceptions.SessionExpiredException;
import org.neo4j.driver.summary.ResultSummary;
import org.neo4j.driver.summary.ServerInfo;
@Readiness
@ApplicationScoped
public class Neo4jHealthCheck implements HealthCheck {
private static final Logger log = Logger.getLogger(Neo4jHealthCheck.class);
/**
* The Cypher statement used to verify Neo4j is up.
*/
private static final String CYPHER = "RETURN 1 AS result";
/**
* Message indicating that the health check failed.
*/
private static final String MESSAGE_HEALTH_CHECK_FAILED = "Neo4j health check failed";
/**
* Message logged before retrying a health check.
*/
private static final String MESSAGE_SESSION_EXPIRED = "Neo4j session has expired, retrying one single time to retrieve server health.";
/**
* The default session config to use while connecting.
*/
private static final SessionConfig DEFAULT_SESSION_CONFIG = SessionConfig.builder()
.withDefaultAccessMode(AccessMode.WRITE)
.build();
@Inject
Driver driver;
@Override
public HealthCheckResponse call() {
HealthCheckResponseBuilder builder = HealthCheckResponse.named("Neo4j connection health check").up();
try {
driver.verifyConnectivity();
return builder.build();
ResultSummary resultSummary;
// Retry one time when the session has been expired
try {
resultSummary = runHealthCheckQuery();
} catch (SessionExpiredException sessionExpiredException) {
log.warn(MESSAGE_SESSION_EXPIRED);
resultSummary = runHealthCheckQuery();
}
return buildStatusUp(resultSummary, builder);
} catch (Exception e) {
return builder.down().withData("reason", e.getMessage()).build();
}
}
/**
* Applies the given {@link ResultSummary} to the {@link HealthCheckResponseBuilder builder} and calls {@code build}
* afterwards.
*
* @param resultSummary the result summary returned by the server
* @param builder the health builder to be modified
* @return the final {@link HealthCheckResponse health check response}
*/
private static HealthCheckResponse buildStatusUp(ResultSummary resultSummary, HealthCheckResponseBuilder builder) {
ServerInfo serverInfo = resultSummary.server();
builder.withData("server", serverInfo.version() + "@" + serverInfo.address());
String databaseName = resultSummary.database().name();
if (!(databaseName == null || databaseName.trim().isEmpty())) {
builder.withData("database", databaseName.trim());
}
return builder.build();
}
private ResultSummary runHealthCheckQuery() {
// We use WRITE here to make sure UP is returned for a server that supports
// all possible workloads
try (Session session = this.driver.session(DEFAULT_SESSION_CONFIG)) {
ResultSummary resultSummary = session.run(CYPHER).consume();
return resultSummary;
}
}
}

View File

@@ -25,7 +25,7 @@
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-bom</artifactId>
<version>Californium-SR9</version>
<version>Dysprosium-RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -203,7 +203,7 @@
<configuration>
<images>
<image>
<name>neo4j:3.5.6</name>
<name>neo4j/neo4j-experimental:4.0.0-rc01</name>
<run>
<ports>
<port>60513:7687</port>

View File

@@ -14,14 +14,13 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Result;
import org.neo4j.driver.Session;
import org.neo4j.driver.StatementResult;
import org.neo4j.driver.Transaction;
import org.neo4j.driver.Values;
import org.neo4j.driver.async.AsyncSession;
import org.neo4j.driver.async.StatementResultCursor;
import org.neo4j.driver.reactive.RxResult;
import org.neo4j.driver.reactive.RxSession;
import org.neo4j.driver.reactive.RxStatementResult;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
@@ -75,9 +74,9 @@ public class Neo4jResource {
public Publisher<Integer> doStuffWithNeo4jReactive() {
return Flux.using(driver::rxSession, session -> session.readTransaction(tx -> {
RxStatementResult result = tx.run("UNWIND range(1, 3) AS x RETURN x", Collections.emptyMap());
RxResult result = tx.run("UNWIND range(1, 3) AS x RETURN x", Collections.emptyMap());
return Flux.from(result.records()).map(record -> record.get("x").asInt());
}), RxSession::close);
}), RxSession::close).doOnNext(System.out::println);
}
private static void createNodes(Driver driver) {
@@ -92,7 +91,7 @@ public class Neo4jResource {
private static void readNodes(Driver driver) {
try (Session session = driver.session();
Transaction transaction = session.beginTransaction()) {
StatementResult result = transaction
Result result = transaction
.run("MATCH (f:Framework {name: $name}) - [:CAN_USE] -> (n) RETURN f, n",
Values.parameters("name", "Quarkus"));
result.forEachRemaining(
@@ -102,25 +101,6 @@ public class Neo4jResource {
}
}
private static void readNodesAsync(Driver driver) {
AsyncSession session = driver.asyncSession();
session
.runAsync("UNWIND range(1, 3) AS x RETURN x")
.thenCompose(StatementResultCursor::listAsync)
.whenComplete((records, error) -> {
if (records != null) {
System.out.println(records);
} else {
error.printStackTrace();
}
})
.thenCompose(records -> {
System.out.println("clsoing!!!");
return session.closeAsync()
.thenApply(ignore -> records);
});
}
private void reportException(String errorMessage, final Exception e, final PrintWriter writer) {
if (errorMessage != null) {
writer.write(errorMessage);

View File

@@ -5,7 +5,6 @@ import static org.hamcrest.Matchers.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
@@ -16,7 +15,7 @@ import io.restassured.RestAssured;
* Can quickly start a matching database with:
*
* <pre>
* docker run --publish=7474:7474 --publish=7687:7687 -e 'NEO4J_AUTH=neo4j/music' neo4j:3.5.3
* docker run --publish=7474:7474 --publish=7687:7687 -e 'NEO4J_AUTH=neo4j/music' neo4j/neo4j-experimental:4.0.0-rc01
* </pre>
*/
@QuarkusTest
@@ -36,7 +35,6 @@ public class Neo4jFunctionalityTest {
}
@Test
@Disabled // Works only with Neo4j 4.0
public void testReactiveNeo4jFunctionality() {
RestAssured.given()
.when().get("/neo4j/reactive")
@@ -46,10 +44,12 @@ public class Neo4jFunctionalityTest {
}
@Test
public void health() throws Exception {
public void health() {
RestAssured.when().get("/health/ready").then()
.log().all()
.body("status", is("UP"),
"checks.status", containsInAnyOrder("UP"),
"checks.name", containsInAnyOrder("Neo4j connection health check"));
"checks.name", containsInAnyOrder("Neo4j connection health check"),
"checks.data.server", containsInAnyOrder(matchesRegex("Neo4j/.*@.*:\\d*")));
}
}