Skip to content

Commit 1ae6bca

Browse files
committed
Add support for GQL-status objects (neo4j#1555)
1 parent a917cc9 commit 1ae6bca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1390
-393
lines changed

driver/clirr-ignored-differences.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,4 +603,28 @@
603603
<method>org.neo4j.driver.ExecutableQuery withAuthToken(org.neo4j.driver.AuthToken)</method>
604604
</difference>
605605

606+
<difference>
607+
<className>org/neo4j/driver/summary/ResultSummary</className>
608+
<differenceType>7012</differenceType>
609+
<method>java.util.Set gqlStatusObjects()</method>
610+
</difference>
611+
612+
<difference>
613+
<className>org/neo4j/driver/summary/Notification</className>
614+
<differenceType>7012</differenceType>
615+
<method>java.util.Optional inputPosition()</method>
616+
</difference>
617+
618+
<difference>
619+
<className>org/neo4j/driver/summary/Notification</className>
620+
<differenceType>7012</differenceType>
621+
<method>java.util.Optional classification()</method>
622+
</difference>
623+
624+
<difference>
625+
<className>org/neo4j/driver/summary/Notification</className>
626+
<differenceType>7012</differenceType>
627+
<method>java.util.Optional rawClassification()</method>
628+
</difference>
629+
606630
</differences>

driver/src/main/java/org/neo4j/driver/Config.java

Lines changed: 88 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING;
2121
import static org.neo4j.driver.internal.util.DriverInfoUtil.driverVersion;
2222

23+
import io.netty.channel.EventLoop;
2324
import java.io.File;
2425
import java.io.Serial;
2526
import java.io.Serializable;
@@ -28,15 +29,22 @@
2829
import java.util.Collections;
2930
import java.util.List;
3031
import java.util.Objects;
32+
import java.util.Optional;
33+
import java.util.Set;
3134
import java.util.concurrent.TimeUnit;
3235
import java.util.logging.Level;
36+
import java.util.stream.Collectors;
37+
import org.neo4j.driver.async.AsyncSession;
3338
import org.neo4j.driver.exceptions.UnsupportedFeatureException;
39+
import org.neo4j.driver.internal.InternalNotificationConfig;
3440
import org.neo4j.driver.internal.RoutingSettings;
3541
import org.neo4j.driver.internal.SecuritySettings;
3642
import org.neo4j.driver.internal.retry.ExponentialBackoffRetryLogic;
3743
import org.neo4j.driver.net.ServerAddressResolver;
3844
import org.neo4j.driver.util.Experimental;
3945
import org.neo4j.driver.util.Immutable;
46+
import org.neo4j.driver.util.Preview;
47+
import org.neo4j.driver.util.Resource;
4048

4149
/**
4250
* A configuration class to config driver properties.
@@ -221,6 +229,7 @@ public int connectionTimeoutMillis() {
221229

222230
/**
223231
* Returns the maximum connection pool size.
232+
*
224233
* @return the maximum size
225234
*/
226235
public int maxConnectionPoolSize() {
@@ -229,6 +238,7 @@ public int maxConnectionPoolSize() {
229238

230239
/**
231240
* Returns the connection acquisition timeout in milliseconds.
241+
*
232242
* @return the acquisition timeout
233243
*/
234244
public long connectionAcquisitionTimeoutMillis() {
@@ -294,6 +304,7 @@ public long maxTransactionRetryTimeMillis() {
294304

295305
/**
296306
* Returns the fetch size.
307+
*
297308
* @return the fetch size
298309
*/
299310
public long fetchSize() {
@@ -302,6 +313,7 @@ public long fetchSize() {
302313

303314
/**
304315
* Returns notification config.
316+
*
305317
* @return the notification config
306318
* @since 5.7
307319
*/
@@ -310,7 +322,35 @@ public NotificationConfig notificationConfig() {
310322
}
311323

312324
/**
313-
* Returns the number of {@link io.netty.channel.EventLoop} threads.
325+
* Returns a minimum notification severity.
326+
*
327+
* @return an {@link Optional} of minimum {@link NotificationSeverity} or an empty {@link Optional} if it is not set
328+
* @since 5.22.0
329+
*/
330+
@Preview(name = "GQL-status object")
331+
public Optional<NotificationSeverity> minimumNotificationSeverity() {
332+
return Optional.ofNullable(((InternalNotificationConfig) notificationConfig).minimumSeverity());
333+
}
334+
335+
/**
336+
* Returns a set of disabled notification classifications.
337+
* @return the {@link Set} of disabled {@link NotificationClassification}
338+
* @since 5.22.0
339+
*/
340+
@Preview(name = "GQL-status object")
341+
public Set<NotificationClassification> disabledNotificationClassifications() {
342+
var disabledCategories = ((InternalNotificationConfig) notificationConfig).disabledCategories();
343+
return disabledCategories != null
344+
? ((InternalNotificationConfig) notificationConfig)
345+
.disabledCategories().stream()
346+
.map(NotificationClassification.class::cast)
347+
.collect(Collectors.toUnmodifiableSet())
348+
: Collections.emptySet();
349+
}
350+
351+
/**
352+
* Returns the number of {@link EventLoop} threads.
353+
*
314354
* @return the number of threads
315355
*/
316356
public int eventLoopThreads() {
@@ -326,6 +366,7 @@ public boolean isMetricsEnabled() {
326366

327367
/**
328368
* Returns the {@link MetricsAdapter}.
369+
*
329370
* @return the metrics adapter
330371
*/
331372
public MetricsAdapter metricsAdapter() {
@@ -371,6 +412,7 @@ public static final class ConfigBuilder {
371412
private MetricsAdapter metricsAdapter = MetricsAdapter.DEV_NULL;
372413
private long fetchSize = 1000;
373414
private int eventLoopThreads = 0;
415+
374416
private NotificationConfig notificationConfig = NotificationConfig.defaultConfig();
375417

376418
private boolean telemetryDisabled = false;
@@ -397,7 +439,7 @@ public ConfigBuilder withLogging(Logging logging) {
397439
* Enable logging of leaked sessions.
398440
* <p>
399441
* Each {@link Session session} is associated with a network connection and thus is a
400-
* {@link org.neo4j.driver.util.Resource resource} that needs to be explicitly closed.
442+
* {@link Resource resource} that needs to be explicitly closed.
401443
* Unclosed sessions will result in socket leaks and could cause {@link OutOfMemoryError}s.
402444
* <p>
403445
* Session is considered to be leaked when it is finalized via {@link Object#finalize()} while not being
@@ -577,8 +619,8 @@ public ConfigBuilder withTrustStrategy(TrustStrategy trustStrategy) {
577619
public ConfigBuilder withRoutingTablePurgeDelay(long delay, TimeUnit unit) {
578620
var routingTablePurgeDelayMillis = unit.toMillis(delay);
579621
if (routingTablePurgeDelayMillis < 0) {
580-
throw new IllegalArgumentException(String.format(
581-
"The routing table purge delay may not be smaller than 0, but was %d %s.", delay, unit));
622+
throw new IllegalArgumentException(
623+
format("The routing table purge delay may not be smaller than 0, but was %d %s.", delay, unit));
582624
}
583625
this.routingTablePurgeDelayMillis = routingTablePurgeDelayMillis;
584626
return this;
@@ -589,11 +631,11 @@ public ConfigBuilder withRoutingTablePurgeDelay(long delay, TimeUnit unit) {
589631
* This config is only valid when the driver is used with servers that support Bolt V4 (Server version 4.0 and later).
590632
* <p>
591633
* Bolt V4 enables pulling records in batches to allow client to take control of data population and apply back pressure to server.
592-
* This config specifies the default fetch size for all query runs using {@link Session} and {@link org.neo4j.driver.async.AsyncSession}.
634+
* This config specifies the default fetch size for all query runs using {@link Session} and {@link AsyncSession}.
593635
* By default, the value is set to {@code 1000}.
594636
* Use {@code -1} to disables back pressure and config client to pull all records at once after each run.
595637
* <p>
596-
* This config only applies to run results obtained via {@link Session} and {@link org.neo4j.driver.async.AsyncSession}.
638+
* This config only applies to run results obtained via {@link Session} and {@link AsyncSession}.
597639
* As with the reactive sessions the batch size is managed by the subscription requests instead.
598640
*
599641
* @param size the default record fetch size when pulling records in batches using Bolt V4.
@@ -629,11 +671,11 @@ public ConfigBuilder withConnectionTimeout(long value, TimeUnit unit) {
629671
var connectionTimeoutMillis = unit.toMillis(value);
630672
if (connectionTimeoutMillis < 0) {
631673
throw new IllegalArgumentException(
632-
String.format("The connection timeout may not be smaller than 0, but was %d %s.", value, unit));
674+
format("The connection timeout may not be smaller than 0, but was %d %s.", value, unit));
633675
}
634676
var connectionTimeoutMillisInt = (int) connectionTimeoutMillis;
635677
if (connectionTimeoutMillisInt != connectionTimeoutMillis) {
636-
throw new IllegalArgumentException(String.format(
678+
throw new IllegalArgumentException(format(
637679
"The connection timeout must represent int value when converted to milliseconds %d.",
638680
connectionTimeoutMillis));
639681
}
@@ -657,7 +699,7 @@ public ConfigBuilder withMaxTransactionRetryTime(long value, TimeUnit unit) {
657699
var maxRetryTimeMs = unit.toMillis(value);
658700
if (maxRetryTimeMs < 0) {
659701
throw new IllegalArgumentException(
660-
String.format("The max retry time may not be smaller than 0, but was %d %s.", value, unit));
702+
format("The max retry time may not be smaller than 0, but was %d %s.", value, unit));
661703
}
662704
this.maxTransactionRetryTimeMillis = maxRetryTimeMs;
663705
return this;
@@ -734,7 +776,7 @@ public ConfigBuilder withMetricsAdapter(MetricsAdapter metricsAdapter) {
734776
public ConfigBuilder withEventLoopThreads(int size) {
735777
if (size < 1) {
736778
throw new IllegalArgumentException(
737-
String.format("The event loop thread may not be smaller than 1, but was %d.", size));
779+
format("The event loop thread may not be smaller than 1, but was %d.", size));
738780
}
739781
this.eventLoopThreads = size;
740782
return this;
@@ -770,6 +812,42 @@ public ConfigBuilder withNotificationConfig(NotificationConfig notificationConfi
770812
return this;
771813
}
772814

815+
/**
816+
* Sets a minimum severity for notifications produced by the server.
817+
*
818+
* @param minimumNotificationSeverity the minimum notification severity
819+
* @return this builder
820+
* @since 5.22.0
821+
*/
822+
@Preview(name = "GQL-status object")
823+
public ConfigBuilder withMinimumNotificationSeverity(NotificationSeverity minimumNotificationSeverity) {
824+
if (minimumNotificationSeverity == null) {
825+
notificationConfig = NotificationConfig.disableAllConfig();
826+
} else {
827+
notificationConfig = notificationConfig.enableMinimumSeverity(minimumNotificationSeverity);
828+
}
829+
return this;
830+
}
831+
832+
/**
833+
* Sets a set of disabled classifications for notifications produced by the server.
834+
*
835+
* @param disabledNotificationClassifications the set of disabled notification classifications
836+
* @return this builder
837+
* @since 5.22.0
838+
*/
839+
@Preview(name = "GQL-status object")
840+
public ConfigBuilder withDisabledNotificationClassifications(
841+
Set<NotificationClassification> disabledNotificationClassifications) {
842+
var disabledCategories = disabledNotificationClassifications == null
843+
? Collections.<NotificationCategory>emptySet()
844+
: disabledNotificationClassifications.stream()
845+
.map(NotificationCategory.class::cast)
846+
.collect(Collectors.toSet());
847+
notificationConfig = notificationConfig.disableCategories(disabledCategories);
848+
return this;
849+
}
850+
773851
/**
774852
* Sets if telemetry is disabled on the driver side.
775853
* <p>

driver/src/main/java/org/neo4j/driver/NotificationCategory.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,50 +17,48 @@
1717
package org.neo4j.driver;
1818

1919
import java.io.Serializable;
20-
import org.neo4j.driver.internal.InternalNotificationCategory;
21-
import org.neo4j.driver.internal.InternalNotificationCategory.Type;
2220

2321
/**
2422
* Notification category.
2523
*
2624
* @since 5.7
2725
*/
28-
public sealed interface NotificationCategory extends Serializable permits InternalNotificationCategory {
26+
public sealed interface NotificationCategory extends Serializable permits NotificationClassification {
2927
/**
3028
* A hint category.
3129
* <p>
3230
* For instance, the given hint cannot be satisfied.
3331
*/
34-
NotificationCategory HINT = new InternalNotificationCategory(Type.HINT);
32+
NotificationCategory HINT = NotificationClassification.HINT;
3533

3634
/**
3735
* An unrecognized category.
3836
* <p>
3937
* For instance, the query or command mentions entities that are unknown to the system.
4038
*/
41-
NotificationCategory UNRECOGNIZED = new InternalNotificationCategory(Type.UNRECOGNIZED);
39+
NotificationCategory UNRECOGNIZED = NotificationClassification.UNRECOGNIZED;
4240

4341
/**
4442
* An unsupported category.
4543
* <p>
4644
* For instance, the query/command is trying to use features that are not supported by the current system or using
4745
* features that are experimental and should not be used in production.
4846
*/
49-
NotificationCategory UNSUPPORTED = new InternalNotificationCategory(Type.UNSUPPORTED);
47+
NotificationCategory UNSUPPORTED = NotificationClassification.UNSUPPORTED;
5048

5149
/**
5250
* A performance category.
5351
* <p>
5452
* For instance, the query uses costly operations and might be slow.
5553
*/
56-
NotificationCategory PERFORMANCE = new InternalNotificationCategory(Type.PERFORMANCE);
54+
NotificationCategory PERFORMANCE = NotificationClassification.PERFORMANCE;
5755

5856
/**
5957
* A deprecation category.
6058
* <p>
6159
* For instance, the query/command use deprecated features that should be replaced.
6260
*/
63-
NotificationCategory DEPRECATION = new InternalNotificationCategory(Type.DEPRECATION);
61+
NotificationCategory DEPRECATION = NotificationClassification.DEPRECATION;
6462

6563
/**
6664
* A security category.
@@ -72,7 +70,7 @@ public sealed interface NotificationCategory extends Serializable permits Intern
7270
*
7371
* @since 5.14
7472
*/
75-
NotificationCategory SECURITY = new InternalNotificationCategory(Type.SECURITY);
73+
NotificationCategory SECURITY = NotificationClassification.SECURITY;
7674

7775
/**
7876
* A topology category.
@@ -84,12 +82,12 @@ public sealed interface NotificationCategory extends Serializable permits Intern
8482
*
8583
* @since 5.14
8684
*/
87-
NotificationCategory TOPOLOGY = new InternalNotificationCategory(Type.TOPOLOGY);
85+
NotificationCategory TOPOLOGY = NotificationClassification.TOPOLOGY;
8886

8987
/**
9088
* A generic category.
9189
* <p>
9290
* For instance, notifications that are not part of a more specific class.
9391
*/
94-
NotificationCategory GENERIC = new InternalNotificationCategory(Type.GENERIC);
92+
NotificationCategory GENERIC = NotificationClassification.GENERIC;
9593
}

0 commit comments

Comments
 (0)