From c5270cfc1230eb3cef84721c0ed273b170a49cd0 Mon Sep 17 00:00:00 2001 From: Andrew Prudhomme Date: Wed, 18 Oct 2023 15:21:14 -0700 Subject: [PATCH] Update gradle and plugin versions, java 14->17 (#600) * Update gradle and plugin versions, java 14->17 * Review feedback --- Dockerfile | 12 +- README.md | 2 +- build.gradle | 38 +-- clientlib/build.gradle | 15 +- docs/introduction.rst | 2 +- example-plugin/build.gradle | 8 +- .../gradle/wrapper/gradle-wrapper.jar | Bin 59821 -> 59536 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 257 +++++++++++------- gradlew.bat | 25 +- grpc-gateway/Dockerfile | 17 +- grpc-gateway/analysis.pb.go | 1 + grpc-gateway/luceneserver.pb.go | 252 +++++++++-------- grpc-gateway/search.pb.go | 104 +++---- grpc-gateway/suggest.pb.go | 9 +- .../server/backup/ContentDownloader.java | 12 +- .../server/grpc/LuceneServerClient.java | 4 +- .../server/grpc/ReplicationServerClient.java | 2 +- .../server/luceneserver/ServerCodec.java | 1 + .../server/luceneserver/SimpleCopyJob.java | 2 +- .../server/luceneserver/doc/VectorType.java | 4 +- .../luceneserver/field/IndexableFieldDef.java | 1 + .../field/properties/Bindable.java | 1 + .../highlights/HighlighterService.java | 1 + .../index/BackendStateManager.java | 10 +- .../search/collectors/HitCountCollector.java | 1 + .../ScriptTermsCollectorManager.java | 1 + .../additional/TermsCollectorManager.java | 1 + .../state/BackendGlobalState.java | 28 +- .../warming/ReservoirSampler.java | 4 +- .../server/plugins/MetricsPlugin.java | 4 +- .../document/Completion90PostingsFormat.java | 1 + .../suggest/document/MyContextQuery.java | 1 + ...NodeNameResolverAndLoadBalancingTests.java | 1 + .../config/LuceneServerConfigurationTest.java | 20 -- .../nrtsearch/server/grpc/AckedCopyTest.java | 1 + .../nrtsearch/server/grpc/CopyFileTest.java | 1 + .../server/grpc/CustomFieldTypeTest.java | 1 + .../server/grpc/LuceneServerIdFieldTest.java | 1 + .../server/grpc/LuceneServerTest.java | 1 + .../server/grpc/MergeBehaviorTests.java | 1 + .../yelp/nrtsearch/server/grpc/QueryTest.java | 1 + .../server/grpc/ReplicationServerTest.java | 2 + .../grpc/ReplicationTestFailureScenarios.java | 2 + .../server/grpc/StateBackendServerTest.java | 18 +- .../nrtsearch/server/grpc/SuggestTest.java | 1 + .../server/luceneserver/ServerTestCase.java | 2 + .../field/MultivaluedObjectTest.java | 3 +- .../index/BackendStateManagerTest.java | 18 +- .../index/ImmutableIndexStateTest.java | 9 +- .../luceneserver/script/ScoreScriptTest.java | 1 + .../search/collectors/CollectorTest.java | 8 +- .../TermsCollectorManagerTestsBase.java | 6 +- .../state/PutRemoteStateCommandTest.java | 6 +- .../state/StateCommandUtilsTest.java | 3 +- 57 files changed, 499 insertions(+), 433 deletions(-) diff --git a/Dockerfile b/Dockerfile index dfe181a75..f25bef109 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,17 @@ -FROM azul/zulu-openjdk-debian:14 +FROM debian:12 ENV DEBIAN_FRONTEND noninteractive +RUN apt-get update && \ + apt-get install -y wget gnupg2 software-properties-common + +RUN wget -O- https://apt.corretto.aws/corretto.key | apt-key add - +RUN add-apt-repository -y 'deb https://apt.corretto.aws stable main' +# For some reason, needs to be run again for the repo to be usable +RUN add-apt-repository -y 'deb https://apt.corretto.aws stable main' +RUN apt-get update && \ + apt-get install -y java-17-amazon-corretto-jdk + RUN mkdir /usr/app/ COPY . /user/app/ WORKDIR /user/app/ diff --git a/README.md b/README.md index 288a4c675..81ff1f5f5 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ In the home directory. ./gradlew clean installDist test ``` -Note: This code has been tested on *Java14* +Note: This code has been tested on *Java17* # Run gRPC Server diff --git a/build.gradle b/build.gradle index 0205cb020..fdb5d0308 100644 --- a/build.gradle +++ b/build.gradle @@ -5,11 +5,11 @@ plugins { id 'idea' id 'maven-publish' id 'signing' - id "com.diffplug.gradle.spotless" version "4.3.0" + id "com.diffplug.spotless" version "6.22.0" id 'java-library' id 'jacoco' // Build docs locally by running "site" command - id 'kr.motd.sphinx' version '2.10.0' + id 'kr.motd.sphinx' version '2.10.1' } repositories { @@ -20,8 +20,10 @@ repositories { mavenCentral() } -sourceCompatibility = 1.14 -targetCompatibility = 1.14 +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} allprojects { version = '1.0.0-SNAPSHOT' @@ -47,7 +49,7 @@ def spatial4jVersion = '0.7' def s3mockVersion = '0.2.5' def commonsCompressVersion = '1.21' def awsJavaSdkVersion = '1.11.695' -def guicedeeVersion = '1.1.1.3-jre14' +def guicedeeVersion = '1.2.2.1-jre17' def prometheusClientVersion = '0.8.0' def fastutilVersion = '8.5.6' @@ -117,32 +119,32 @@ dependencies { startScripts.enabled = false task luceneServer(type: CreateStartScripts) { - mainClassName = 'com.yelp.nrtsearch.server.grpc.LuceneServer' + mainClass = 'com.yelp.nrtsearch.server.grpc.LuceneServer' applicationName = 'lucene-server' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp-app') classpath = startScripts.classpath // Add additional dependencies, e.g. custom loggers classpath += files('$APP_HOME/additional_libs') } task luceneServerClient(type: CreateStartScripts) { - mainClassName = 'com.yelp.nrtsearch.server.cli.LuceneClientCommand' + mainClass = 'com.yelp.nrtsearch.server.cli.LuceneClientCommand' applicationName = 'lucene-client' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp-app') classpath = startScripts.classpath } task backupRestoreTool(type: CreateStartScripts) { - mainClassName = 'com.yelp.nrtsearch.server.cli.BackupRestoreCommand' + mainClass = 'com.yelp.nrtsearch.server.cli.BackupRestoreCommand' applicationName = 'backup-restore' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp-app') classpath = startScripts.classpath } task nrtUtils(type: CreateStartScripts) { - mainClassName = 'com.yelp.nrtsearch.tools.nrt_utils.NrtUtilsCommand' + mainClass = 'com.yelp.nrtsearch.tools.nrt_utils.NrtUtilsCommand' applicationName = 'nrt_utils' - outputDir = new File(project.buildDir, 'tmp') + outputDir = new File(project.buildDir, 'tmp-app') classpath = startScripts.classpath } @@ -165,6 +167,8 @@ task buildGrpcGateway(dependsOn: installDist, type: Exec) { //e.g. default is to exclude perfTests: ./gradlew test test { finalizedBy 'spotlessJavaCheck' + // Used by LuceneServerConfigurationTest + environment(Map.of('CUSTOM_HOST', 'my_custom_host', 'VAR1', 'v1', 'VAR2', 'v2', 'VAR3', 'v3')) if (project.hasProperty('longRunningTestsOnly')) { include '**/IncrementalDataCleanupCommandTest.class' } else { @@ -189,7 +193,7 @@ test { jacocoTestReport { reports { - csv.enabled true + csv.required = true } } @@ -198,17 +202,17 @@ task javadocs(type: Javadoc) { } task javadocsJar(type: Jar) { - classifier('javadoc') + archiveClassifier = 'javadoc' from javadocs.destinationDir } task sourcesJar(type: Jar) { - classifier('sources') + archiveClassifier = 'sources' from sourceSets.main.java.srcDirs } task testsJar(type: Jar) { - classifier('tests') + archiveClassifier = 'tests' from sourceSets.test.output } diff --git a/clientlib/build.gradle b/clientlib/build.gradle index 8a4ef2383..d1491e415 100644 --- a/clientlib/build.gradle +++ b/clientlib/build.gradle @@ -2,13 +2,13 @@ plugins { // Provide convenience executables for trying out the examples. id 'application' // ASSUMES GRADLE 2.12 OR HIGHER. Use plugin version 0.7.5 with earlier gradle versions - id 'com.google.protobuf' version '0.8.12' + id 'com.google.protobuf' version '0.9.4' // Generate IntelliJ IDEA's .idea & .iml project files id 'idea' // Publish clientlib to maven central id 'maven-publish' id 'signing' - id "com.diffplug.gradle.spotless" + id "com.diffplug.spotless" id 'java-library' } @@ -20,8 +20,10 @@ repositories { mavenCentral() } -sourceCompatibility = 1.8 -targetCompatibility = 1.8 +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} startScripts.enabled = false // groupId, artifactId and version for the generated pom @@ -88,12 +90,12 @@ task javadocs(type: Javadoc) { } task javadocsJar(type: Jar) { - classifier('javadoc') + archiveClassifier = 'javadoc' from javadocs.destinationDir } task sourcesJar(type: Jar) { - classifier('sources') + archiveClassifier = 'sources' from sourceSets.main.java.srcDirs } @@ -183,6 +185,7 @@ publishing { spotless { java { + targetExclude "build/**/*.java" licenseHeaderFile '../license_header' removeUnusedImports() endWithNewline() diff --git a/docs/introduction.rst b/docs/introduction.rst index c9c412fcc..864c41efb 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -56,7 +56,7 @@ In the home directory, one can build nrtSearch locally like this: ./gradlew clean installDist test -Note: This code has been tested on *Java14*. +Note: This code has been tested on *Java17*. Run gRPC Server --------------------------- diff --git a/example-plugin/build.gradle b/example-plugin/build.gradle index 14ecb9691..6722011cd 100644 --- a/example-plugin/build.gradle +++ b/example-plugin/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'com.diffplug.gradle.spotless' version '4.3.0' + id 'com.diffplug.spotless' version '6.22.0' id 'distribution' // Generate IntelliJ IDEA's .idea & .iml project files id 'idea' @@ -14,8 +14,10 @@ repositories { mavenCentral() } -sourceCompatibility = 1.17 -targetCompatibility = 1.17 +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} group 'com.yelp.nrtsearch.plugins' version '0.0.1' diff --git a/example-plugin/gradle/wrapper/gradle-wrapper.jar b/example-plugin/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d4fb3f96a785543079b8df6723c946b..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 8722 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 delta 8958 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 delta 21233 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -105,79 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 24467a141..ac1b06f93 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/grpc-gateway/Dockerfile b/grpc-gateway/Dockerfile index f2412a487..2a7a8da17 100644 --- a/grpc-gateway/Dockerfile +++ b/grpc-gateway/Dockerfile @@ -1,9 +1,17 @@ -FROM azul/zulu-openjdk-debian:14 +FROM debian:12 RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y wget unzip htop \ golang-go \ - git + git \ + gnupg2 software-properties-common + +RUN wget -O- https://apt.corretto.aws/corretto.key | apt-key add - +RUN add-apt-repository -y 'deb https://apt.corretto.aws stable main' +# For some reason, needs to be run again for the repo to be usable +RUN add-apt-repository -y 'deb https://apt.corretto.aws stable main' +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y java-17-amazon-corretto-jdk # Install protoc ENV PROTOC_VERSION=3.11.4 @@ -45,6 +53,11 @@ RUN go get \ github.com/golang/protobuf/protoc-gen-go@v${PROTOC_GEN_GO_VERSION} \ google.golang.org/grpc@v${GRPC_VERSION} +RUN go install \ + github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway@v${GRPC_GATEWAY_VERSION} \ + github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger@v${GRPC_GATEWAY_VERSION} +RUN go install github.com/golang/protobuf/protoc-gen-go@v${PROTOC_GEN_GO_VERSION} + ENV PROTO_PATH=/code/clientlib/src/main/proto ENV PROTO_BUILD_PATH=/code/clientlib/build diff --git a/grpc-gateway/analysis.pb.go b/grpc-gateway/analysis.pb.go index 2996321d1..11794dab6 100644 --- a/grpc-gateway/analysis.pb.go +++ b/grpc-gateway/analysis.pb.go @@ -281,6 +281,7 @@ type Analyzer struct { unknownFields protoimpl.UnknownFields // Types that are assignable to AnalyzerType: + // // *Analyzer_Predefined // *Analyzer_Custom AnalyzerType isAnalyzer_AnalyzerType `protobuf_oneof:"AnalyzerType"` diff --git a/grpc-gateway/luceneserver.pb.go b/grpc-gateway/luceneserver.pb.go index fd1b12342..d2c3011dd 100644 --- a/grpc-gateway/luceneserver.pb.go +++ b/grpc-gateway/luceneserver.pb.go @@ -32,7 +32,7 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -//Type of the field +// Type of the field type FieldType int32 const ( @@ -127,7 +127,7 @@ func (FieldType) EnumDescriptor() ([]byte, []int) { return file_yelp_nrtsearch_luceneserver_proto_rawDescGZIP(), []int{0} } -//How the tokens should be indexed. +// How the tokens should be indexed. type IndexOptions int32 const ( @@ -180,7 +180,7 @@ func (IndexOptions) EnumDescriptor() ([]byte, []int) { return file_yelp_nrtsearch_luceneserver_proto_rawDescGZIP(), []int{1} } -//Whether/how term vectors should be indexed. +// Whether/how term vectors should be indexed. type TermVectors int32 const ( @@ -236,7 +236,7 @@ func (TermVectors) EnumDescriptor() ([]byte, []int) { return file_yelp_nrtsearch_luceneserver_proto_rawDescGZIP(), []int{2} } -//Whether/How this field should index facets, and how. +// Whether/How this field should index facets, and how. type FacetType int32 const ( @@ -633,31 +633,31 @@ type LiveSettingsRequest struct { unknownFields protoimpl.UnknownFields IndexName string `protobuf:"bytes,1,opt,name=indexName,proto3" json:"indexName,omitempty"` // name of index whose liveSettings are to be updated. - //Longest time to wait before reopening IndexSearcher (i.e., periodic background reopen). + // Longest time to wait before reopening IndexSearcher (i.e., periodic background reopen). MaxRefreshSec float64 `protobuf:"fixed64,2,opt,name=maxRefreshSec,proto3" json:"maxRefreshSec,omitempty"` - //Shortest time to wait before reopening IndexSearcher (i.e., when a search is waiting for a specific indexGen). + // Shortest time to wait before reopening IndexSearcher (i.e., when a search is waiting for a specific indexGen). MinRefreshSec float64 `protobuf:"fixed64,3,opt,name=minRefreshSec,proto3" json:"minRefreshSec,omitempty"` - //Non-current searchers older than this are pruned. + // Non-current searchers older than this are pruned. MaxSearcherAgeSec float64 `protobuf:"fixed64,4,opt,name=maxSearcherAgeSec,proto3" json:"maxSearcherAgeSec,omitempty"` - //Size (in MB) of IndexWriter's RAM buffer. + // Size (in MB) of IndexWriter's RAM buffer. IndexRamBufferSizeMB float64 `protobuf:"fixed64,5,opt,name=indexRamBufferSizeMB,proto3" json:"indexRamBufferSizeMB,omitempty"` - //Max number of documents to add at a time. + // Max number of documents to add at a time. AddDocumentsMaxBufferLen int32 `protobuf:"varint,6,opt,name=addDocumentsMaxBufferLen,proto3" json:"addDocumentsMaxBufferLen,omitempty"` - //Maximum number of documents allowed in a parallel search slice. + // Maximum number of documents allowed in a parallel search slice. SliceMaxDocs int32 `protobuf:"varint,7,opt,name=sliceMaxDocs,proto3" json:"sliceMaxDocs,omitempty"` - //Maximum number of segments allowed in a parallel search slice. + // Maximum number of segments allowed in a parallel search slice. SliceMaxSegments int32 `protobuf:"varint,8,opt,name=sliceMaxSegments,proto3" json:"sliceMaxSegments,omitempty"` - //Number of virtual shards to use for this index. + // Number of virtual shards to use for this index. VirtualShards int32 `protobuf:"varint,9,opt,name=virtualShards,proto3" json:"virtualShards,omitempty"` - //Maximum sized segment to produce during normal merging + // Maximum sized segment to produce during normal merging MaxMergedSegmentMB int32 `protobuf:"varint,10,opt,name=maxMergedSegmentMB,proto3" json:"maxMergedSegmentMB,omitempty"` - //Number of segments per tier used by TieredMergePolicy + // Number of segments per tier used by TieredMergePolicy SegmentsPerTier int32 `protobuf:"varint,11,opt,name=segmentsPerTier,proto3" json:"segmentsPerTier,omitempty"` - //Timeout value to used when not specified in the search request. + // Timeout value to used when not specified in the search request. DefaultSearchTimeoutSec float64 `protobuf:"fixed64,12,opt,name=defaultSearchTimeoutSec,proto3" json:"defaultSearchTimeoutSec,omitempty"` - //Timeout check every value to use when not specified in the search request. + // Timeout check every value to use when not specified in the search request. DefaultSearchTimeoutCheckEvery int32 `protobuf:"varint,13,opt,name=defaultSearchTimeoutCheckEvery,proto3" json:"defaultSearchTimeoutCheckEvery,omitempty"` - //Terminate after value to use when not specified in the search request. + // Terminate after value to use when not specified in the search request. DefaultTerminateAfter int32 `protobuf:"varint,14,opt,name=defaultTerminateAfter,proto3" json:"defaultTerminateAfter,omitempty"` } @@ -966,12 +966,12 @@ type Field struct { DocValuesFormat string `protobuf:"bytes,14,opt,name=docValuesFormat,proto3" json:"docValuesFormat,omitempty"` // Which DocValuesFormat should be used to index this field. IndexOptions IndexOptions `protobuf:"varint,15,opt,name=indexOptions,proto3,enum=luceneserver.IndexOptions" json:"indexOptions,omitempty"` //How the tokens should be indexed. Script *Script `protobuf:"bytes,16,opt,name=script,proto3" json:"script,omitempty"` // The script definition defining a virtual field's value (only used with type=virtual). - //TODO make analyzers message types i.e. StandardAnalyzer, EnglishAnalyzer, CustomAnalyzer etc + // TODO make analyzers message types i.e. StandardAnalyzer, EnglishAnalyzer, CustomAnalyzer etc Analyzer *Analyzer `protobuf:"bytes,17,opt,name=analyzer,proto3" json:"analyzer,omitempty"` // Analyzer to use for this field during indexing and searching. IndexAnalyzer *Analyzer `protobuf:"bytes,18,opt,name=indexAnalyzer,proto3" json:"indexAnalyzer,omitempty"` // Analyzer to use for this field during indexing. SearchAnalyzer *Analyzer `protobuf:"bytes,19,opt,name=searchAnalyzer,proto3" json:"searchAnalyzer,omitempty"` //Analyzer to use for this field during searching. TermVectors TermVectors `protobuf:"varint,20,opt,name=termVectors,proto3,enum=luceneserver.TermVectors" json:"termVectors,omitempty"` // Whether/how term vectors should be indexed. - //TODO make similarity message types i.d. DefaultSimilarity, CustomSimilarity, BM25Similarity; + // TODO make similarity message types i.d. DefaultSimilarity, CustomSimilarity, BM25Similarity; Similarity string `protobuf:"bytes,21,opt,name=similarity,proto3" json:"similarity,omitempty"` // Which Similarity implementation to use for this field. Facet FacetType `protobuf:"varint,22,opt,name=facet,proto3,enum=luceneserver.FacetType" json:"facet,omitempty"` // Whether this field should index facets, and how. FacetIndexFieldName string `protobuf:"bytes,23,opt,name=facetIndexFieldName,proto3" json:"facetIndexFieldName,omitempty"` // "Which underlying Lucene index field is used to hold any indexed taxonomy or sorted set doc values facets @@ -2222,8 +2222,9 @@ type CommitResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // sequence number of the last operation in the commit. All sequence numbers less than this value - //will be reflected in the commit, and all others will not. + // sequence number of the last operation in the commit. All sequence numbers less than this value + // + // will be reflected in the commit, and all others will not. Gen int64 `protobuf:"varint,1,opt,name=gen,proto3" json:"gen,omitempty"` // Unique identifier for the primary instance that processed the request PrimaryId string `protobuf:"bytes,2,opt,name=primaryId,proto3" json:"primaryId,omitempty"` @@ -2329,9 +2330,9 @@ type StatsResponse struct { Ord int32 `protobuf:"varint,1,opt,name=ord,proto3" json:"ord,omitempty"` //shard ordinal // The total number of docs in this index, including docs not yet flushed (still in the RAM buffer), - //not counting deletions. + // not counting deletions. MaxDoc int32 `protobuf:"varint,2,opt,name=maxDoc,proto3" json:"maxDoc,omitempty"` - //* + // * // The total number of docs in this index, including // docs not yet flushed (still in the RAM buffer), and // including deletions. NOTE: buffered deletions @@ -2494,7 +2495,7 @@ type Searcher struct { unknownFields protoimpl.UnknownFields // the version recorded in the commit that the reader opened. - //This version is advanced every time a change is made with IndexWriter. + // This version is advanced every time a change is made with IndexWriter. Version int64 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` NumDocs int32 `protobuf:"varint,2,opt,name=numDocs,proto3" json:"numDocs,omitempty"` //total number of docs in this index Segments string `protobuf:"bytes,3,opt,name=segments,proto3" json:"segments,omitempty"` //string representation of segments @@ -2927,21 +2928,20 @@ func (*ReloadStateResponse) Descriptor() ([]byte, []int) { return file_yelp_nrtsearch_luceneserver_proto_rawDescGZIP(), []int{35} } -// -//Creates a snapshot in the index, which is saved point-in-time view of the last commit in the -//index such that no files referenced by that snapshot will be deleted by ongoing indexing until -//the snapshot is released with @releaseSnapshot. Note that this will reference the last commit, -//so be sure to call commit first if you have pending changes that you'd like to be included in -//the snapshot.

This can be used for backup purposes, i.e. after creating the snapshot you can -//copy all referenced files to backup storage, and then release the snapshot once complete. -//To restore the backup, just copy all the files back and restart the server. It can also -//be used for transactional purposes, i.e. if you sometimes need to search a specific snapshot -//instead of the current live index.

Creating a snapshot is very fast (does not require any -//file copying), but over time it will consume extra disk space as old segments are merged in -//the index. Be sure to release the snapshot once you're done. Snapshots survive shutdown -//and restart of the server. Returns all protected filenames referenced by this snapshot: -//these files will not change and will not be deleted until the snapshot is released. -//This returns the directories and files referenced by the snapshot. +// Creates a snapshot in the index, which is saved point-in-time view of the last commit in the +// index such that no files referenced by that snapshot will be deleted by ongoing indexing until +// the snapshot is released with @releaseSnapshot. Note that this will reference the last commit, +// so be sure to call commit first if you have pending changes that you'd like to be included in +// the snapshot.

This can be used for backup purposes, i.e. after creating the snapshot you can +// copy all referenced files to backup storage, and then release the snapshot once complete. +// To restore the backup, just copy all the files back and restart the server. It can also +// be used for transactional purposes, i.e. if you sometimes need to search a specific snapshot +// instead of the current live index.

Creating a snapshot is very fast (does not require any +// file copying), but over time it will consume extra disk space as old segments are merged in +// the index. Be sure to release the snapshot once you're done. Snapshots survive shutdown +// and restart of the server. Returns all protected filenames referenced by this snapshot: +// these files will not change and will not be deleted until the snapshot is released. +// This returns the directories and files referenced by the snapshot. type CreateSnapshotRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -4389,7 +4389,7 @@ func (x *FileMetadata) GetFooter() []byte { return nil } -//* Primary invokes this on a replica to ask it to copy files +// * Primary invokes this on a replica to ask it to copy files type CopyFiles struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -4461,7 +4461,7 @@ func (x *CopyFiles) GetFilesMetadata() *FilesMetadata { return nil } -//* Replica invokes this on a primary to let primary know it needs the CopyState +// * Replica invokes this on a primary to let primary know it needs the CopyState type CopyStateRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -6110,14 +6110,14 @@ func (x *CustomResponse) GetResponse() map[string]string { return nil } -//we use this wrapper object to represent each field as a multivalued field. +// we use this wrapper object to represent each field as a multivalued field. type AddDocumentRequest_MultiValuedField struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Value []string `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` //list of values for this field - //Facet paths/hierarchy to bucket these values by, if indexed field is of type Facet.HIERARCHY + // Facet paths/hierarchy to bucket these values by, if indexed field is of type Facet.HIERARCHY FaceHierarchyPaths []*FacetHierarchyPath `protobuf:"bytes,2,rep,name=faceHierarchyPaths,proto3" json:"faceHierarchyPaths,omitempty"` } @@ -8838,20 +8838,20 @@ type LuceneServerClient interface { // Change global offline or online settings for this index. LiveSettingsV2(ctx context.Context, in *LiveSettingsV2Request, opts ...grpc.CallOption) (*LiveSettingsV2Response, error) // Registers one or more fields. Fields must be registered before they can be added in a document (via @addDocument). - //Pass a list of Fields and an indexName. Any number of fields may be registered in a single request, - //and once a field is registered it cannot be changed (write-once). - //This returns the full set of fields currently registered. + // Pass a list of Fields and an indexName. Any number of fields may be registered in a single request, + // and once a field is registered it cannot be changed (write-once). + // This returns the full set of fields currently registered. RegisterFields(ctx context.Context, in *FieldDefRequest, opts ...grpc.CallOption) (*FieldDefResponse, error) // Adds one or more fields. Fields must be registered before they can be added in a document (via @addDocument). - //Pass a list of Fields and an indexName. Any number of fields may be registered in a single request, - //and once a field is registered it cannot be changed (write-once). - //This returns the full set of fields currently registered. + // Pass a list of Fields and an indexName. Any number of fields may be registered in a single request, + // and once a field is registered it cannot be changed (write-once). + // This returns the full set of fields currently registered. UpdateFields(ctx context.Context, in *FieldDefRequest, opts ...grpc.CallOption) (*FieldDefResponse, error) // Change global offline settings for this index. - //This returns the currently set settings; pass no settings changes to retrieve current settings. + // This returns the currently set settings; pass no settings changes to retrieve current settings. Settings(ctx context.Context, in *SettingsRequest, opts ...grpc.CallOption) (*SettingsResponse, error) // Change global offline settings for this index. - //This returns the currently set settings; pass no settings to retrieve current settings. + // This returns the currently set settings; pass no settings to retrieve current settings. SettingsV2(ctx context.Context, in *SettingsV2Request, opts ...grpc.CallOption) (*SettingsV2Response, error) // Starts an index StartIndex(ctx context.Context, in *StartIndexRequest, opts ...grpc.CallOption) (*StartIndexResponse, error) @@ -8887,22 +8887,21 @@ type LuceneServerClient interface { SuggestLookup(ctx context.Context, in *SuggestLookupRequest, opts ...grpc.CallOption) (*SuggestLookupResponse, error) // Updates existing suggestions, if the suggester supports near-real-time changes. UpdateSuggest(ctx context.Context, in *BuildSuggestRequest, opts ...grpc.CallOption) (*BuildSuggestResponse, error) - // - //Creates a snapshot in the index, which is saved point-in-time view of the last commit - //in the index such that no files referenced by that snapshot will be deleted by ongoing - //indexing until the snapshot is released with @releaseSnapshot. Note that this will - //reference the last commit, so be sure to call commit first if you have pending changes - //that you'd like to be included in the snapshot. - //This can be used for backup purposes, i.e. after creating the snapshot you can copy - //all referenced files to backup storage, and then release the snapshot once complete. - //To restore the backup, just copy all the files back and restart the server. - //It can also be used for transactional purposes, i.e. if you sometimes need to search a - //specific snapshot instead of the current live index. Creating a snapshot is very fast - //(does not require any file copying), but over time it will consume extra disk space as - //old segments are merged in the index. Be sure to release the snapshot once you're done. - //Snapshots survive shutdown and restart of the server. Returns all protected filenames - //referenced by this snapshot: these files will not change and will not be deleted until - //the snapshot is released. This returns the directories and files referenced by the snapshot. + // Creates a snapshot in the index, which is saved point-in-time view of the last commit + // in the index such that no files referenced by that snapshot will be deleted by ongoing + // indexing until the snapshot is released with @releaseSnapshot. Note that this will + // reference the last commit, so be sure to call commit first if you have pending changes + // that you'd like to be included in the snapshot. + // This can be used for backup purposes, i.e. after creating the snapshot you can copy + // all referenced files to backup storage, and then release the snapshot once complete. + // To restore the backup, just copy all the files back and restart the server. + // It can also be used for transactional purposes, i.e. if you sometimes need to search a + // specific snapshot instead of the current live index. Creating a snapshot is very fast + // (does not require any file copying), but over time it will consume extra disk space as + // old segments are merged in the index. Be sure to release the snapshot once you're done. + // Snapshots survive shutdown and restart of the server. Returns all protected filenames + // referenced by this snapshot: these files will not change and will not be deleted until + // the snapshot is released. This returns the directories and files referenced by the snapshot. CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*CreateSnapshotResponse, error) // releases a snapshot previously created with @createSnapshot. ReleaseSnapshot(ctx context.Context, in *ReleaseSnapshotRequest, opts ...grpc.CallOption) (*ReleaseSnapshotResponse, error) @@ -8917,30 +8916,26 @@ type LuceneServerClient interface { State(ctx context.Context, in *StateRequest, opts ...grpc.CallOption) (*StateResponse, error) // healthcheck Status(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) - // - //Checks if a node is ready to receive traffic by checking if all the indices (which can be preloaded) - //are started. Can specify comma-separated list of index name to only check specific indices if needed. + // Checks if a node is ready to receive traffic by checking if all the indices (which can be preloaded) + // are started. Can specify comma-separated list of index name to only check specific indices if needed. Ready(ctx context.Context, in *ReadyCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) // metrics Metrics(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*httpbody.HttpBody, error) // indices Indices(ctx context.Context, in *IndicesRequest, opts ...grpc.CallOption) (*IndicesResponse, error) - // - //Forces merge policy to merge segments until there are <= maxNumSegments. The actual - //merges to be executed are determined by the MergePolicy. This call will merge those - //segments present in the index when the call started. If other threads are still - //adding documents and flushing segments, those newly created segments will not be - //merged unless you call forceMerge again. + // Forces merge policy to merge segments until there are <= maxNumSegments. The actual + // merges to be executed are determined by the MergePolicy. This call will merge those + // segments present in the index when the call started. If other threads are still + // adding documents and flushing segments, those newly created segments will not be + // merged unless you call forceMerge again. ForceMerge(ctx context.Context, in *ForceMergeRequest, opts ...grpc.CallOption) (*ForceMergeResponse, error) - // - //Forces merging of all segments that have deleted documents. The actual merges to be - //executed are determined by the MergePolicy. For example, the default TieredMergePolicy - //will only pick a segment if the percentage of deleted docs is over 10%. - //This method first flushes a new segment (if there are indexed documents), and applies - //all buffered deletes. + // Forces merging of all segments that have deleted documents. The actual merges to be + // executed are determined by the MergePolicy. For example, the default TieredMergePolicy + // will only pick a segment if the percentage of deleted docs is over 10%. + // This method first flushes a new segment (if there are indexed documents), and applies + // all buffered deletes. ForceMergeDeletes(ctx context.Context, in *ForceMergeDeletesRequest, opts ...grpc.CallOption) (*ForceMergeDeletesResponse, error) - // - //Process request in a plugin which implements CustomRequestPlugin interface. + // Process request in a plugin which implements CustomRequestPlugin interface. Custom(ctx context.Context, in *CustomRequest, opts ...grpc.CallOption) (*CustomResponse, error) } @@ -9328,20 +9323,20 @@ type LuceneServerServer interface { // Change global offline or online settings for this index. LiveSettingsV2(context.Context, *LiveSettingsV2Request) (*LiveSettingsV2Response, error) // Registers one or more fields. Fields must be registered before they can be added in a document (via @addDocument). - //Pass a list of Fields and an indexName. Any number of fields may be registered in a single request, - //and once a field is registered it cannot be changed (write-once). - //This returns the full set of fields currently registered. + // Pass a list of Fields and an indexName. Any number of fields may be registered in a single request, + // and once a field is registered it cannot be changed (write-once). + // This returns the full set of fields currently registered. RegisterFields(context.Context, *FieldDefRequest) (*FieldDefResponse, error) // Adds one or more fields. Fields must be registered before they can be added in a document (via @addDocument). - //Pass a list of Fields and an indexName. Any number of fields may be registered in a single request, - //and once a field is registered it cannot be changed (write-once). - //This returns the full set of fields currently registered. + // Pass a list of Fields and an indexName. Any number of fields may be registered in a single request, + // and once a field is registered it cannot be changed (write-once). + // This returns the full set of fields currently registered. UpdateFields(context.Context, *FieldDefRequest) (*FieldDefResponse, error) // Change global offline settings for this index. - //This returns the currently set settings; pass no settings changes to retrieve current settings. + // This returns the currently set settings; pass no settings changes to retrieve current settings. Settings(context.Context, *SettingsRequest) (*SettingsResponse, error) // Change global offline settings for this index. - //This returns the currently set settings; pass no settings to retrieve current settings. + // This returns the currently set settings; pass no settings to retrieve current settings. SettingsV2(context.Context, *SettingsV2Request) (*SettingsV2Response, error) // Starts an index StartIndex(context.Context, *StartIndexRequest) (*StartIndexResponse, error) @@ -9377,22 +9372,21 @@ type LuceneServerServer interface { SuggestLookup(context.Context, *SuggestLookupRequest) (*SuggestLookupResponse, error) // Updates existing suggestions, if the suggester supports near-real-time changes. UpdateSuggest(context.Context, *BuildSuggestRequest) (*BuildSuggestResponse, error) - // - //Creates a snapshot in the index, which is saved point-in-time view of the last commit - //in the index such that no files referenced by that snapshot will be deleted by ongoing - //indexing until the snapshot is released with @releaseSnapshot. Note that this will - //reference the last commit, so be sure to call commit first if you have pending changes - //that you'd like to be included in the snapshot. - //This can be used for backup purposes, i.e. after creating the snapshot you can copy - //all referenced files to backup storage, and then release the snapshot once complete. - //To restore the backup, just copy all the files back and restart the server. - //It can also be used for transactional purposes, i.e. if you sometimes need to search a - //specific snapshot instead of the current live index. Creating a snapshot is very fast - //(does not require any file copying), but over time it will consume extra disk space as - //old segments are merged in the index. Be sure to release the snapshot once you're done. - //Snapshots survive shutdown and restart of the server. Returns all protected filenames - //referenced by this snapshot: these files will not change and will not be deleted until - //the snapshot is released. This returns the directories and files referenced by the snapshot. + // Creates a snapshot in the index, which is saved point-in-time view of the last commit + // in the index such that no files referenced by that snapshot will be deleted by ongoing + // indexing until the snapshot is released with @releaseSnapshot. Note that this will + // reference the last commit, so be sure to call commit first if you have pending changes + // that you'd like to be included in the snapshot. + // This can be used for backup purposes, i.e. after creating the snapshot you can copy + // all referenced files to backup storage, and then release the snapshot once complete. + // To restore the backup, just copy all the files back and restart the server. + // It can also be used for transactional purposes, i.e. if you sometimes need to search a + // specific snapshot instead of the current live index. Creating a snapshot is very fast + // (does not require any file copying), but over time it will consume extra disk space as + // old segments are merged in the index. Be sure to release the snapshot once you're done. + // Snapshots survive shutdown and restart of the server. Returns all protected filenames + // referenced by this snapshot: these files will not change and will not be deleted until + // the snapshot is released. This returns the directories and files referenced by the snapshot. CreateSnapshot(context.Context, *CreateSnapshotRequest) (*CreateSnapshotResponse, error) // releases a snapshot previously created with @createSnapshot. ReleaseSnapshot(context.Context, *ReleaseSnapshotRequest) (*ReleaseSnapshotResponse, error) @@ -9407,30 +9401,26 @@ type LuceneServerServer interface { State(context.Context, *StateRequest) (*StateResponse, error) // healthcheck Status(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) - // - //Checks if a node is ready to receive traffic by checking if all the indices (which can be preloaded) - //are started. Can specify comma-separated list of index name to only check specific indices if needed. + // Checks if a node is ready to receive traffic by checking if all the indices (which can be preloaded) + // are started. Can specify comma-separated list of index name to only check specific indices if needed. Ready(context.Context, *ReadyCheckRequest) (*HealthCheckResponse, error) // metrics Metrics(context.Context, *emptypb.Empty) (*httpbody.HttpBody, error) // indices Indices(context.Context, *IndicesRequest) (*IndicesResponse, error) - // - //Forces merge policy to merge segments until there are <= maxNumSegments. The actual - //merges to be executed are determined by the MergePolicy. This call will merge those - //segments present in the index when the call started. If other threads are still - //adding documents and flushing segments, those newly created segments will not be - //merged unless you call forceMerge again. + // Forces merge policy to merge segments until there are <= maxNumSegments. The actual + // merges to be executed are determined by the MergePolicy. This call will merge those + // segments present in the index when the call started. If other threads are still + // adding documents and flushing segments, those newly created segments will not be + // merged unless you call forceMerge again. ForceMerge(context.Context, *ForceMergeRequest) (*ForceMergeResponse, error) - // - //Forces merging of all segments that have deleted documents. The actual merges to be - //executed are determined by the MergePolicy. For example, the default TieredMergePolicy - //will only pick a segment if the percentage of deleted docs is over 10%. - //This method first flushes a new segment (if there are indexed documents), and applies - //all buffered deletes. + // Forces merging of all segments that have deleted documents. The actual merges to be + // executed are determined by the MergePolicy. For example, the default TieredMergePolicy + // will only pick a segment if the percentage of deleted docs is over 10%. + // This method first flushes a new segment (if there are indexed documents), and applies + // all buffered deletes. ForceMergeDeletes(context.Context, *ForceMergeDeletesRequest) (*ForceMergeDeletesResponse, error) - // - //Process request in a plugin which implements CustomRequestPlugin interface. + // Process request in a plugin which implements CustomRequestPlugin interface. Custom(context.Context, *CustomRequest) (*CustomResponse, error) } @@ -10429,11 +10419,11 @@ type ReplicationServerClient interface { CopyFiles(ctx context.Context, in *CopyFiles, opts ...grpc.CallOption) (ReplicationServer_CopyFilesClient, error) // Invoked externally to replica, to notify it that a new NRT point was just created on the primary NewNRTPoint(ctx context.Context, in *NewNRTPoint, opts ...grpc.CallOption) (*TransferStatus, error) - //* Invoked externally to primary, to make all recent index operations searchable on the primary and, once copying is done, on the replicas + // * Invoked externally to primary, to make all recent index operations searchable on the primary and, once copying is done, on the replicas WriteNRTPoint(ctx context.Context, in *IndexName, opts ...grpc.CallOption) (*SearcherVersion, error) - //* Invoked externally to replica, to get the current Searcher version on replica. + // * Invoked externally to replica, to get the current Searcher version on replica. GetCurrentSearcherVersion(ctx context.Context, in *IndexName, opts ...grpc.CallOption) (*SearcherVersion, error) - //* Invoked externally on primary to find the list of replica nodes this node is connected to for binary replication per index + // * Invoked externally on primary to find the list of replica nodes this node is connected to for binary replication per index GetConnectedNodes(ctx context.Context, in *GetNodesRequest, opts ...grpc.CallOption) (*GetNodesResponse, error) } @@ -10643,11 +10633,11 @@ type ReplicationServerServer interface { CopyFiles(*CopyFiles, ReplicationServer_CopyFilesServer) error // Invoked externally to replica, to notify it that a new NRT point was just created on the primary NewNRTPoint(context.Context, *NewNRTPoint) (*TransferStatus, error) - //* Invoked externally to primary, to make all recent index operations searchable on the primary and, once copying is done, on the replicas + // * Invoked externally to primary, to make all recent index operations searchable on the primary and, once copying is done, on the replicas WriteNRTPoint(context.Context, *IndexName) (*SearcherVersion, error) - //* Invoked externally to replica, to get the current Searcher version on replica. + // * Invoked externally to replica, to get the current Searcher version on replica. GetCurrentSearcherVersion(context.Context, *IndexName) (*SearcherVersion, error) - //* Invoked externally on primary to find the list of replica nodes this node is connected to for binary replication per index + // * Invoked externally on primary to find the list of replica nodes this node is connected to for binary replication per index GetConnectedNodes(context.Context, *GetNodesRequest) (*GetNodesResponse, error) } diff --git a/grpc-gateway/search.pb.go b/grpc-gateway/search.pb.go index 792747b32..6008ebcf5 100644 --- a/grpc-gateway/search.pb.go +++ b/grpc-gateway/search.pb.go @@ -649,7 +649,7 @@ func (Script_ParamNullValue) EnumDescriptor() ([]byte, []int) { return file_yelp_nrtsearch_search_proto_rawDescGZIP(), []int{27, 0} } -//* How the {TotalHits#value} should be interpreted. +// * How the {TotalHits#value} should be interpreted. type TotalHits_Relation int32 const ( @@ -698,7 +698,7 @@ func (TotalHits_Relation) EnumDescriptor() ([]byte, []int) { return file_yelp_nrtsearch_search_proto_rawDescGZIP(), []int{31, 0} } -//Sorting order type +// Sorting order type type BucketOrder_OrderType int32 const ( @@ -989,7 +989,7 @@ type PhraseQuery struct { unknownFields protoimpl.UnknownFields // Edit distance between respective positions of terms as defined in this PhraseQuery and the positions - //of terms in a document. + // of terms in a document. Slop int32 `protobuf:"varint,1,opt,name=slop,proto3" json:"slop,omitempty"` Field string `protobuf:"bytes,2,opt,name=field,proto3" json:"field,omitempty"` // The field in the index that this query applies to. Terms []string `protobuf:"bytes,3,rep,name=terms,proto3" json:"terms,omitempty"` // Terms to match. @@ -1228,7 +1228,6 @@ func (x *FunctionFilterQuery) GetScript() *Script { return nil } -// type NestedQuery struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1301,6 +1300,7 @@ type TermQuery struct { // Field in the document to query. Field string `protobuf:"bytes,1,opt,name=field,proto3" json:"field,omitempty"` // Types that are assignable to TermTypes: + // // *TermQuery_TextValue // *TermQuery_IntValue // *TermQuery_LongValue @@ -1453,6 +1453,7 @@ type TermInSetQuery struct { // Field in the document to query. Field string `protobuf:"bytes,1,opt,name=field,proto3" json:"field,omitempty"` // Types that are assignable to TermTypes: + // // *TermInSetQuery_TextTerms_ // *TermInSetQuery_IntTerms_ // *TermInSetQuery_LongTerms_ @@ -2555,6 +2556,7 @@ type Query struct { QueryType QueryType `protobuf:"varint,1,opt,name=queryType,proto3,enum=luceneserver.QueryType" json:"queryType,omitempty"` // no longer needed, type inferred from set QueryNode Boost float32 `protobuf:"fixed32,2,opt,name=boost,proto3" json:"boost,omitempty"` // Boost values that are less than one will give less importance to this query compared to other ones while values that are greater than one will give more importance to the scores returned by this query. Boost value of zero will do nothing (default). Boost less than 0 is invalid. // Types that are assignable to QueryNode: + // // *Query_BooleanQuery // *Query_PhraseQuery // *Query_FunctionScoreQuery @@ -2927,6 +2929,7 @@ type SearchRequest struct { Query *Query `protobuf:"bytes,8,opt,name=query,proto3" json:"query,omitempty"` // Full query to execute using QueryNodes QuerySort *QuerySortField `protobuf:"bytes,9,opt,name=querySort,proto3" json:"querySort,omitempty"` //Sort hits by field (default is by relevance). // Types that are assignable to Searcher: + // // *SearchRequest_IndexGen // *SearchRequest_Version // *SearchRequest_Snapshot @@ -2937,15 +2940,15 @@ type SearchRequest struct { DisallowPartialResults bool `protobuf:"varint,16,opt,name=disallowPartialResults,proto3" json:"disallowPartialResults,omitempty"` //Should partial result be a failure condition. Applies when a search request times out. If false, the top documents ranking at the point of timeout are used and the request continues. Also, hitTimeout is set to true in the response. QueryNestedPath string `protobuf:"bytes,17,opt,name=queryNestedPath,proto3" json:"queryNestedPath,omitempty"` //nested path we want to query by if we want to query child documents. Rescorers []*Rescorer `protobuf:"bytes,18,rep,name=rescorers,proto3" json:"rescorers,omitempty"` // Rescorers which are executed in-order after the first pass - //If detailed request execution profiling should be included in the response + // If detailed request execution profiling should be included in the response Profile bool `protobuf:"varint,19,opt,name=profile,proto3" json:"profile,omitempty"` - //Check the search timeout condition after each collection of n documents in a segment. If 0, timeout is only checked on the segment boundary. + // Check the search timeout condition after each collection of n documents in a segment. If 0, timeout is only checked on the segment boundary. TimeoutCheckEvery int32 `protobuf:"varint,20,opt,name=timeoutCheckEvery,proto3" json:"timeoutCheckEvery,omitempty"` - //Additional document collectors. Provides support for operations such as aggregation. + // Additional document collectors. Provides support for operations such as aggregation. Collectors map[string]*Collector `protobuf:"bytes,21,rep,name=collectors,proto3" json:"collectors,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - //Stop document collection in search phase after this many documents, 0 for unlimited. + // Stop document collection in search phase after this many documents, 0 for unlimited. TerminateAfter int32 `protobuf:"varint,22,opt,name=terminateAfter,proto3" json:"terminateAfter,omitempty"` - //Set gRPC compression codec to use for response message. If value is unset or invalid, falls back to uncompressed. Valid codecs: identity, gzip, lz4 + // Set gRPC compression codec to use for response message. If value is unset or invalid, falls back to uncompressed. Valid codecs: identity, gzip, lz4 ResponseCompression string `protobuf:"bytes,23,opt,name=responseCompression,proto3" json:"responseCompression,omitempty"` // Specify how to highlight matched text Highlight *Highlight `protobuf:"bytes,24,opt,name=highlight,proto3" json:"highlight,omitempty"` @@ -3550,8 +3553,8 @@ type SortType struct { Selector Selector `protobuf:"varint,2,opt,name=selector,proto3,enum=luceneserver.Selector" json:"selector,omitempty"` // For multi valued fields, how to select which value is used for sorting Origin *Point `protobuf:"bytes,3,opt,name=origin,proto3" json:"origin,omitempty"` // For distance sort, the point that we measure distance from // Whether missing values should sort last instead of first. - //Note that this runs \"before\" reverse, so if you sort missing first and reverse=true then missing values will - //be at the end. + // Note that this runs \"before\" reverse, so if you sort missing first and reverse=true then missing values will + // be at the end. MissingLat bool `protobuf:"varint,4,opt,name=missingLat,proto3" json:"missingLat,omitempty"` // Sort in reverse of the field's natural order Reverse bool `protobuf:"varint,5,opt,name=reverse,proto3" json:"reverse,omitempty"` @@ -3630,7 +3633,7 @@ type TotalHits struct { unknownFields protoimpl.UnknownFields Relation TotalHits_Relation `protobuf:"varint,1,opt,name=relation,proto3,enum=luceneserver.TotalHits_Relation" json:"relation,omitempty"` - //* The value of the total hit count. Must be interpreted in the context of * {#relation}. + // * The value of the total hit count. Must be interpreted in the context of * {#relation}. Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` } @@ -4365,6 +4368,7 @@ type Rescorer struct { WindowSize int32 `protobuf:"varint,1,opt,name=windowSize,proto3" json:"windowSize,omitempty"` // Types that are assignable to Rescorers: + // // *Rescorer_QueryRescorer // *Rescorer_PluginRescorer Rescorers isRescorer_Rescorers `protobuf_oneof:"Rescorers"` @@ -4527,20 +4531,21 @@ func (x *ProfileResult) GetDrillDownQuery() string { return "" } -//Definition of additional document collector. +// Definition of additional document collector. type Collector struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to Collectors: + // // *Collector_Terms // *Collector_PluginCollector // *Collector_TopHitsCollector // *Collector_Filter // *Collector_Max Collectors isCollector_Collectors `protobuf_oneof:"Collectors"` - //Nested collectors that define sub-aggregations per bucket, supported by bucket based collectors. + // Nested collectors that define sub-aggregations per bucket, supported by bucket based collectors. NestedCollectors map[string]*Collector `protobuf:"bytes,3,rep,name=nestedCollectors,proto3" json:"nestedCollectors,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -4630,7 +4635,7 @@ type isCollector_Collectors interface { } type Collector_Terms struct { - //Collector for aggregating based on term values. + // Collector for aggregating based on term values. Terms *TermsCollector `protobuf:"bytes,1,opt,name=terms,proto3,oneof"` } @@ -4639,17 +4644,17 @@ type Collector_PluginCollector struct { } type Collector_TopHitsCollector struct { - //Collector for getting top hits based on score or sorting. + // Collector for getting top hits based on score or sorting. TopHitsCollector *TopHitsCollector `protobuf:"bytes,4,opt,name=topHitsCollector,proto3,oneof"` } type Collector_Filter struct { - //Collector that filters documents to nested collectors + // Collector that filters documents to nested collectors Filter *FilterCollector `protobuf:"bytes,5,opt,name=filter,proto3,oneof"` } type Collector_Max struct { - //Collector for finding a max double value from collected documents. + // Collector for finding a max double value from collected documents. Max *MaxCollector `protobuf:"bytes,6,opt,name=max,proto3,oneof"` } @@ -4719,19 +4724,20 @@ func (x *PluginCollector) GetParams() *structpb.Struct { return nil } -//Definition of term aggregating collector. +// Definition of term aggregating collector. type TermsCollector struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to TermsSource: + // // *TermsCollector_Field // *TermsCollector_Script TermsSource isTermsCollector_TermsSource `protobuf_oneof:"TermsSource"` - //Maximum number of top terms to return. + // Maximum number of top terms to return. Size int32 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"` - //How results Buckets should be ordered, defaults to descending Bucket _count. + // How results Buckets should be ordered, defaults to descending Bucket _count. Order *BucketOrder `protobuf:"bytes,4,opt,name=order,proto3" json:"order,omitempty"` } @@ -4807,12 +4813,12 @@ type isTermsCollector_TermsSource interface { } type TermsCollector_Field struct { - //Use field values for terms. + // Use field values for terms. Field string `protobuf:"bytes,1,opt,name=field,proto3,oneof"` } type TermsCollector_Script struct { - //Use FacetScript definition to produce terms. + // Use FacetScript definition to produce terms. Script *Script `protobuf:"bytes,2,opt,name=script,proto3,oneof"` } @@ -4820,19 +4826,19 @@ func (*TermsCollector_Field) isTermsCollector_TermsSource() {} func (*TermsCollector_Script) isTermsCollector_TermsSource() {} -//Definition of top hits based collector. +// Definition of top hits based collector. type TopHitsCollector struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - //Offset for retrieval of top hits. + // Offset for retrieval of top hits. StartHit int32 `protobuf:"varint,1,opt,name=startHit,proto3" json:"startHit,omitempty"` - //Total hits to collect, note that the number of hits returned is (topHits - startHit). + // Total hits to collect, note that the number of hits returned is (topHits - startHit). TopHits int32 `protobuf:"varint,2,opt,name=topHits,proto3" json:"topHits,omitempty"` - //When specified, collector does sort based collection. Otherwise, relevance score is used. + // When specified, collector does sort based collection. Otherwise, relevance score is used. QuerySort *QuerySortField `protobuf:"bytes,3,opt,name=querySort,proto3" json:"querySort,omitempty"` - //Which fields to retrieve. + // Which fields to retrieve. RetrieveFields []string `protobuf:"bytes,4,rep,name=retrieveFields,proto3" json:"retrieveFields,omitempty"` // If Lucene explanation should be included in the collector response Explain bool `protobuf:"varint,5,opt,name=explain,proto3" json:"explain,omitempty"` @@ -4905,13 +4911,14 @@ func (x *TopHitsCollector) GetExplain() bool { return false } -//Definition of filtering collector, there must be at least one nested collector specified in the Collector message. +// Definition of filtering collector, there must be at least one nested collector specified in the Collector message. type FilterCollector struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to Filter: + // // *FilterCollector_Query // *FilterCollector_SetQuery Filter isFilterCollector_Filter `protobuf_oneof:"Filter"` @@ -4988,13 +4995,14 @@ func (*FilterCollector_Query) isFilterCollector_Filter() {} func (*FilterCollector_SetQuery) isFilterCollector_Filter() {} -//Definition of collector to find a max double value over documents. Currently only allows for script based value production. +// Definition of collector to find a max double value over documents. Currently only allows for script based value production. type MaxCollector struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to ValueSource: + // // *MaxCollector_Script ValueSource isMaxCollector_ValueSource `protobuf_oneof:"ValueSource"` } @@ -5050,7 +5058,7 @@ type isMaxCollector_ValueSource interface { } type MaxCollector_Script struct { - //Script to produce a double value + // Script to produce a double value Script *Script `protobuf:"bytes,1,opt,name=script,proto3,oneof"` } @@ -5062,6 +5070,7 @@ type CollectorResult struct { unknownFields protoimpl.UnknownFields // Types that are assignable to CollectorResults: + // // *CollectorResult_BucketResult // *CollectorResult_AnyResult // *CollectorResult_HitsResult @@ -5149,27 +5158,27 @@ type isCollectorResult_CollectorResults interface { } type CollectorResult_BucketResult struct { - //Result of collector that produces buckets and counts. + // Result of collector that produces buckets and counts. BucketResult *BucketResult `protobuf:"bytes,1,opt,name=bucketResult,proto3,oneof"` } type CollectorResult_AnyResult struct { - //Flexible collector result for additional document collectors + // Flexible collector result for additional document collectors AnyResult *anypb.Any `protobuf:"bytes,2,opt,name=anyResult,proto3,oneof"` } type CollectorResult_HitsResult struct { - //Result of collector that returns document hits. + // Result of collector that returns document hits. HitsResult *HitsResult `protobuf:"bytes,4,opt,name=hitsResult,proto3,oneof"` } type CollectorResult_FilterResult struct { - //Result of collector that filters documents. + // Result of collector that filters documents. FilterResult *FilterResult `protobuf:"bytes,5,opt,name=filterResult,proto3,oneof"` } type CollectorResult_DoubleResult struct { - //Result of collector that produces a single double value. + // Result of collector that produces a single double value. DoubleResult *wrapperspb.DoubleValue `protobuf:"bytes,6,opt,name=doubleResult,proto3,oneof"` } @@ -5183,15 +5192,15 @@ func (*CollectorResult_FilterResult) isCollectorResult_CollectorResults() {} func (*CollectorResult_DoubleResult) isCollectorResult_CollectorResults() {} -//Defines how Buckets should be ordered in BucketResult. +// Defines how Buckets should be ordered in BucketResult. type BucketOrder struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - //What to use for sorting. This can be _count for Bucket count, or the name of a nested collector that supports ordering. + // What to use for sorting. This can be _count for Bucket count, or the name of a nested collector that supports ordering. Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - //Sorting order + // Sorting order Order BucketOrder_OrderType `protobuf:"varint,2,opt,name=order,proto3,enum=luceneserver.BucketOrder_OrderType" json:"order,omitempty"` } @@ -5247,9 +5256,9 @@ type BucketResult struct { unknownFields protoimpl.UnknownFields Buckets []*BucketResult_Bucket `protobuf:"bytes,1,rep,name=buckets,proto3" json:"buckets,omitempty"` - //Number of unique buckets, including those not in the buckets list. + // Number of unique buckets, including those not in the buckets list. TotalBuckets int32 `protobuf:"varint,2,opt,name=totalBuckets,proto3" json:"totalBuckets,omitempty"` - //Number of other collected counts not represented in the buckets' counts. + // Number of other collected counts not represented in the buckets' counts. TotalOtherCounts int32 `protobuf:"varint,3,opt,name=totalOtherCounts,proto3" json:"totalOtherCounts,omitempty"` } @@ -5311,9 +5320,9 @@ type HitsResult struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - //Total hit information. + // Total hit information. TotalHits *TotalHits `protobuf:"bytes,3,opt,name=totalHits,proto3" json:"totalHits,omitempty"` - //Ordered hits with scoring/sorting info and retrieved fields. + // Ordered hits with scoring/sorting info and retrieved fields. Hits []*SearchResponse_Hit `protobuf:"bytes,4,rep,name=hits,proto3" json:"hits,omitempty"` } @@ -5368,9 +5377,9 @@ type FilterResult struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - //Number of documents that passed the filter. + // Number of documents that passed the filter. DocCount int32 `protobuf:"varint,1,opt,name=docCount,proto3" json:"docCount,omitempty"` - //Results from nested collectors. + // Results from nested collectors. NestedCollectorResults map[string]*CollectorResult `protobuf:"bytes,2,rep,name=nestedCollectorResults,proto3" json:"nestedCollectorResults,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -5829,6 +5838,7 @@ type MultiFunctionScoreQuery_FilterFunction struct { // Function to produce score, will be 1.0 if none are set // // Types that are assignable to Function: + // // *MultiFunctionScoreQuery_FilterFunction_Script Function isMultiFunctionScoreQuery_FilterFunction_Function `protobuf_oneof:"Function"` } @@ -5912,6 +5922,7 @@ type Script_ParamValue struct { unknownFields protoimpl.UnknownFields // Types that are assignable to ParamValues: + // // *Script_ParamValue_TextValue // *Script_ParamValue_BooleanValue // *Script_ParamValue_IntValue @@ -6572,6 +6583,7 @@ type SearchResponse_Hit_FieldValue struct { unknownFields protoimpl.UnknownFields // Types that are assignable to FieldValues: + // // *SearchResponse_Hit_FieldValue_TextValue // *SearchResponse_Hit_FieldValue_BooleanValue // *SearchResponse_Hit_FieldValue_IntValue @@ -7174,7 +7186,7 @@ type BucketResult_Bucket struct { Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` Count int32 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"` - //Nested collector results for sub-aggregations of this bucket. + // Nested collector results for sub-aggregations of this bucket. NestedCollectorResults map[string]*CollectorResult `protobuf:"bytes,8,rep,name=nestedCollectorResults,proto3" json:"nestedCollectorResults,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } diff --git a/grpc-gateway/suggest.pb.go b/grpc-gateway/suggest.pb.go index 06f59d2a5..f7559d20f 100644 --- a/grpc-gateway/suggest.pb.go +++ b/grpc-gateway/suggest.pb.go @@ -29,6 +29,7 @@ type BuildSuggestRequest struct { IndexName string `protobuf:"bytes,1,opt,name=indexName,proto3" json:"indexName,omitempty"` //index name // Types that are assignable to Suggester: + // // *BuildSuggestRequest_InfixSuggester // *BuildSuggestRequest_AnalyzingSuggester // *BuildSuggestRequest_FuzzySuggester @@ -36,6 +37,7 @@ type BuildSuggestRequest struct { // *BuildSuggestRequest_FuzzyInfixSuggester Suggester isBuildSuggestRequest_Suggester `protobuf_oneof:"Suggester"` // Types that are assignable to Source: + // // *BuildSuggestRequest_LocalSource // *BuildSuggestRequest_NonLocalSource Source isBuildSuggestRequest_Source `protobuf_oneof:"Source"` @@ -409,6 +411,7 @@ type OneSuggestLookupResponse struct { unknownFields protoimpl.UnknownFields // Types that are assignable to HighlightKey: + // // *OneSuggestLookupResponse_SuggestLookupHighlight // *OneSuggestLookupResponse_Key HighlightKey isOneSuggestLookupResponse_HighlightKey `protobuf_oneof:"HighlightKey"` @@ -609,8 +612,8 @@ type SuggestLocalSource struct { unknownFields protoimpl.UnknownFields // Local file (to the server) to read suggestions + weights from; format is weight U+001F suggestion U+001F payload, - //one per line, with suggestion UTF-8 encoded. If this option is used then searcher, suggestField, - //weightField/Expression, payloadField should not be specified. + // one per line, with suggestion UTF-8 encoded. If this option is used then searcher, suggestField, + // weightField/Expression, payloadField should not be specified. LocalFile string `protobuf:"bytes,1,opt,name=localFile,proto3" json:"localFile,omitempty"` HasContexts bool `protobuf:"varint,2,opt,name=hasContexts,proto3" json:"hasContexts,omitempty"` //True if this file provides per-suggestion contexts HasPayload bool `protobuf:"varint,3,opt,name=hasPayload,proto3" json:"hasPayload,omitempty"` //True if this file provides per-suggestion payload @@ -684,12 +687,14 @@ type SuggestNonLocalSource struct { // Specific searcher version to use for pull suggestions to build. There are three different ways to specify a searcher version. // Types that are assignable to Searcher: + // // *SuggestNonLocalSource_IndexGen // *SuggestNonLocalSource_Version // *SuggestNonLocalSource_Snapshot Searcher isSuggestNonLocalSource_Searcher `protobuf_oneof:"Searcher"` SuggestField string `protobuf:"bytes,4,opt,name=suggestField,proto3" json:"suggestField,omitempty"` //Field (from stored documents) containing the suggestion text // Types that are assignable to Weight: + // // *SuggestNonLocalSource_WeightField // *SuggestNonLocalSource_WeightExpression Weight isSuggestNonLocalSource_Weight `protobuf_oneof:"Weight"` diff --git a/src/main/java/com/yelp/nrtsearch/server/backup/ContentDownloader.java b/src/main/java/com/yelp/nrtsearch/server/backup/ContentDownloader.java index ba355b986..77a427bc1 100644 --- a/src/main/java/com/yelp/nrtsearch/server/backup/ContentDownloader.java +++ b/src/main/java/com/yelp/nrtsearch/server/backup/ContentDownloader.java @@ -31,12 +31,18 @@ void getVersionContent( final String serviceName, final String resource, final String hash, final Path destDirectory) throws IOException; - /** @return amazonS3 Client used by this ContentDownloader */ + /** + * @return amazonS3 Client used by this ContentDownloader + */ AmazonS3 getS3Client(); - /** @return bucketName used by this ContentDownloader */ + /** + * @return bucketName used by this ContentDownloader + */ String getBucketName(); - /** @return boolean to indicate if this ContentDownloader operates in stream mode */ + /** + * @return boolean to indicate if this ContentDownloader operates in stream mode + */ boolean downloadAsStream(); } diff --git a/src/main/java/com/yelp/nrtsearch/server/grpc/LuceneServerClient.java b/src/main/java/com/yelp/nrtsearch/server/grpc/LuceneServerClient.java index a91804e47..cacd0d026 100644 --- a/src/main/java/com/yelp/nrtsearch/server/grpc/LuceneServerClient.java +++ b/src/main/java/com/yelp/nrtsearch/server/grpc/LuceneServerClient.java @@ -490,7 +490,9 @@ public void deleteIndexBackup( } public List getIndices() { - return blockingStub.indices(IndicesRequest.newBuilder().build()).getIndicesResponseList() + return blockingStub + .indices(IndicesRequest.newBuilder().build()) + .getIndicesResponseList() .stream() .map(IndexStatsResponse::getIndexName) .collect(Collectors.toList()); diff --git a/src/main/java/com/yelp/nrtsearch/server/grpc/ReplicationServerClient.java b/src/main/java/com/yelp/nrtsearch/server/grpc/ReplicationServerClient.java index 926db5f90..ce693caf1 100644 --- a/src/main/java/com/yelp/nrtsearch/server/grpc/ReplicationServerClient.java +++ b/src/main/java/com/yelp/nrtsearch/server/grpc/ReplicationServerClient.java @@ -41,7 +41,7 @@ public class ReplicationServerClient implements Closeable { public static final int FILE_UPDATE_INTERVAL_MS = 10 * 1000; // 10 seconds private static final ObjectMapper OBJECT_MAPPER = - new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);; + new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); private static final Logger logger = LoggerFactory.getLogger(ReplicationServerClient.class); private final String host; diff --git a/src/main/java/com/yelp/nrtsearch/server/luceneserver/ServerCodec.java b/src/main/java/com/yelp/nrtsearch/server/luceneserver/ServerCodec.java index 586f8ba34..ed2e5fe8f 100644 --- a/src/main/java/com/yelp/nrtsearch/server/luceneserver/ServerCodec.java +++ b/src/main/java/com/yelp/nrtsearch/server/luceneserver/ServerCodec.java @@ -32,6 +32,7 @@ public class ServerCodec extends Lucene95Codec { public static final String DEFAULT_DOC_VALUES_FORMAT = "Lucene90"; private final IndexStateManager stateManager; + // nocommit expose compression control /** Sole constructor. */ diff --git a/src/main/java/com/yelp/nrtsearch/server/luceneserver/SimpleCopyJob.java b/src/main/java/com/yelp/nrtsearch/server/luceneserver/SimpleCopyJob.java index 01d3bab5d..c09931a9f 100644 --- a/src/main/java/com/yelp/nrtsearch/server/luceneserver/SimpleCopyJob.java +++ b/src/main/java/com/yelp/nrtsearch/server/luceneserver/SimpleCopyJob.java @@ -101,7 +101,7 @@ public void start() throws IOException { @Override public void runBlocking() throws Exception { - while (visit() == false) ; + while (visit() == false) {} if (getFailed()) { throw new RuntimeException("copy failed: " + cancelReason, exc); } diff --git a/src/main/java/com/yelp/nrtsearch/server/luceneserver/doc/VectorType.java b/src/main/java/com/yelp/nrtsearch/server/luceneserver/doc/VectorType.java index 9e0125204..e5bc446fb 100644 --- a/src/main/java/com/yelp/nrtsearch/server/luceneserver/doc/VectorType.java +++ b/src/main/java/com/yelp/nrtsearch/server/luceneserver/doc/VectorType.java @@ -61,7 +61,9 @@ public Float set(int index, Float element) { return currentValue; } - /** @return number of elements in the vector */ + /** + * @return number of elements in the vector + */ @Override public int size() { return vectorData.length; diff --git a/src/main/java/com/yelp/nrtsearch/server/luceneserver/field/IndexableFieldDef.java b/src/main/java/com/yelp/nrtsearch/server/luceneserver/field/IndexableFieldDef.java index 51de80ef1..6de3fc06a 100644 --- a/src/main/java/com/yelp/nrtsearch/server/luceneserver/field/IndexableFieldDef.java +++ b/src/main/java/com/yelp/nrtsearch/server/luceneserver/field/IndexableFieldDef.java @@ -290,6 +290,7 @@ public void parseFieldWithChildren( List> facetHierarchyPaths) { parseFieldWithChildren(documentsContext.getRootDocument(), fieldValues, facetHierarchyPaths); } + /** * Parse a list of field values for this field and its children. The values will be those present * in a {@link com.yelp.nrtsearch.server.grpc.AddDocumentRequest.MultiValuedField}. diff --git a/src/main/java/com/yelp/nrtsearch/server/luceneserver/field/properties/Bindable.java b/src/main/java/com/yelp/nrtsearch/server/luceneserver/field/properties/Bindable.java index d76358798..b9dcbadf2 100644 --- a/src/main/java/com/yelp/nrtsearch/server/luceneserver/field/properties/Bindable.java +++ b/src/main/java/com/yelp/nrtsearch/server/luceneserver/field/properties/Bindable.java @@ -23,6 +23,7 @@ */ public interface Bindable { String VALUE_PROPERTY = "value"; + /** * Get {@link DoubleValuesSource} to produce values per document when this field is bound into a * lucene {@link org.apache.lucene.expressions.Expression} script. diff --git a/src/main/java/com/yelp/nrtsearch/server/luceneserver/highlights/HighlighterService.java b/src/main/java/com/yelp/nrtsearch/server/luceneserver/highlights/HighlighterService.java index b3066d122..7fa683051 100644 --- a/src/main/java/com/yelp/nrtsearch/server/luceneserver/highlights/HighlighterService.java +++ b/src/main/java/com/yelp/nrtsearch/server/luceneserver/highlights/HighlighterService.java @@ -50,6 +50,7 @@ private static void initializeBuiltinHighlighters() { NRTFastVectorHighlighter nrtFastVectorHighlighter = NRTFastVectorHighlighter.getInstance(); instance.register(nrtFastVectorHighlighter.getName(), nrtFastVectorHighlighter); } + /** * Initialize singleton instance of {@link HighlighterService}. Registers all builtin highlighter * and any additional highlighter provided by {@link HighlighterPlugin}s. diff --git a/src/main/java/com/yelp/nrtsearch/server/luceneserver/index/BackendStateManager.java b/src/main/java/com/yelp/nrtsearch/server/luceneserver/index/BackendStateManager.java index 8450ab250..48bd6771b 100644 --- a/src/main/java/com/yelp/nrtsearch/server/luceneserver/index/BackendStateManager.java +++ b/src/main/java/com/yelp/nrtsearch/server/luceneserver/index/BackendStateManager.java @@ -208,9 +208,7 @@ public synchronized void start( logger.info("Doing initial commit for index: " + indexName); currentState.commit(globalState.getConfiguration().getBackupWithInArchiver()); IndexStateInfo updatedStateInfo = - currentState - .getCurrentStateInfo() - .toBuilder() + currentState.getCurrentStateInfo().toBuilder() .setCommitted(true) .setGen(currentState.getCurrentStateInfo().getGen() + 1) .build(); @@ -259,8 +257,7 @@ private static IndexStateInfo mergeSettings( IndexStateInfo currentStateInfo, IndexSettings settings) { IndexSettings mergedSettings = ImmutableIndexState.mergeSettings(currentStateInfo.getSettings(), settings); - return currentStateInfo - .toBuilder() + return currentStateInfo.toBuilder() .setSettings(mergedSettings) .setGen(currentStateInfo.getGen() + 1) .build(); @@ -270,8 +267,7 @@ private static IndexStateInfo mergeLiveSettings( IndexStateInfo currentStateInfo, IndexLiveSettings liveSettings) { IndexLiveSettings mergedLiveSettings = ImmutableIndexState.mergeLiveSettings(currentStateInfo.getLiveSettings(), liveSettings); - return currentStateInfo - .toBuilder() + return currentStateInfo.toBuilder() .setLiveSettings(mergedLiveSettings) .setGen(currentStateInfo.getGen() + 1) .build(); diff --git a/src/main/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/HitCountCollector.java b/src/main/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/HitCountCollector.java index e72e77267..1ecf10266 100644 --- a/src/main/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/HitCountCollector.java +++ b/src/main/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/HitCountCollector.java @@ -35,6 +35,7 @@ */ public class HitCountCollector extends DocCollector { private final HitCountCollectorManager manager; + /** * Constructor * diff --git a/src/main/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/additional/ScriptTermsCollectorManager.java b/src/main/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/additional/ScriptTermsCollectorManager.java index 8afbeae54..4daa6f0e6 100644 --- a/src/main/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/additional/ScriptTermsCollectorManager.java +++ b/src/main/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/additional/ScriptTermsCollectorManager.java @@ -46,6 +46,7 @@ /** Collector manager that aggregates terms from a {@link FacetScript} into buckets. */ public class ScriptTermsCollectorManager extends TermsCollectorManager { private final FacetScript.SegmentFactory scriptFactory; + /** * Constructor. * diff --git a/src/main/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/additional/TermsCollectorManager.java b/src/main/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/additional/TermsCollectorManager.java index b9cf0b5ff..0b003bb28 100644 --- a/src/main/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/additional/TermsCollectorManager.java +++ b/src/main/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/additional/TermsCollectorManager.java @@ -221,6 +221,7 @@ public void setSearchContext(SearchContext searchContext) { nestedCollectorManagers.setSearchContext(searchContext); } } + /** Get max number of buckets to return */ public int getSize() { return size; diff --git a/src/main/java/com/yelp/nrtsearch/server/luceneserver/state/BackendGlobalState.java b/src/main/java/com/yelp/nrtsearch/server/luceneserver/state/BackendGlobalState.java index f06bd99d2..209955932 100644 --- a/src/main/java/com/yelp/nrtsearch/server/luceneserver/state/BackendGlobalState.java +++ b/src/main/java/com/yelp/nrtsearch/server/luceneserver/state/BackendGlobalState.java @@ -61,6 +61,7 @@ public class BackendGlobalState extends GlobalState { private static final Logger logger = LoggerFactory.getLogger(BackendGlobalState.class); private int resolvedReplicationPort; + /** * State class containing immutable persistent and ephemeral global state, stored together so that * they can be updated atomically. @@ -290,9 +291,7 @@ public synchronized IndexState createIndex(CreateIndexRequest createIndexRequest } GlobalStateInfo updatedState = - immutableState - .globalStateInfo - .toBuilder() + immutableState.globalStateInfo.toBuilder() .putIndices(indexName, newIndexState) .setGen(immutableState.globalStateInfo.getGen() + 1) .build(); @@ -328,9 +327,7 @@ public IndexStateManager getIndexStateManager(String name) throws IOException { @Override public synchronized void deleteIndex(String name) throws IOException { GlobalStateInfo updatedState = - immutableState - .globalStateInfo - .toBuilder() + immutableState.globalStateInfo.toBuilder() .removeIndices(name) .setGen(immutableState.globalStateInfo.getGen() + 1) .build(); @@ -372,12 +369,9 @@ && getConfiguration() .getResourceName() .equals(startIndexRequest.getIndexName())) { request = - startIndexRequest - .toBuilder() + startIndexRequest.toBuilder() .setRestore( - startIndexRequest - .getRestore() - .toBuilder() + startIndexRequest.getRestore().toBuilder() .setResourceName( getUniqueIndexName( startIndexRequest.getIndexName(), indexGlobalState.getId())) @@ -392,9 +386,7 @@ && getConfiguration() if (startIndexRequest.getMode() != Mode.REPLICA && !indexGlobalState.getStarted()) { IndexGlobalState updatedIndexState = indexGlobalState.toBuilder().setStarted(true).build(); GlobalStateInfo updatedGlobalState = - immutableState - .globalStateInfo - .toBuilder() + immutableState.globalStateInfo.toBuilder() .putIndices(startIndexRequest.getIndexName(), updatedIndexState) .setGen(immutableState.globalStateInfo.getGen() + 1) .build(); @@ -419,9 +411,7 @@ public synchronized StartIndexResponse startIndexV2(StartIndexV2Request startInd if (getConfiguration().getIndexStartConfig().getMode() != Mode.REPLICA) { GlobalStateInfo updatedGlobalState = - immutableState - .globalStateInfo - .toBuilder() + immutableState.globalStateInfo.toBuilder() .putIndices(startIndexRequest.getIndexName(), updatedIndexGlobalState) .setGen(immutableState.globalStateInfo.getGen() + 1) .build(); @@ -471,9 +461,7 @@ public synchronized DummyResponse stopIndex(StopIndexRequest stopIndexRequest) .build(); GlobalStateInfo updatedState = - immutableState - .globalStateInfo - .toBuilder() + immutableState.globalStateInfo.toBuilder() .putIndices(stopIndexRequest.getIndexName(), updatedIndexState) .setGen(immutableState.globalStateInfo.getGen() + 1) .build(); diff --git a/src/main/java/com/yelp/nrtsearch/server/luceneserver/warming/ReservoirSampler.java b/src/main/java/com/yelp/nrtsearch/server/luceneserver/warming/ReservoirSampler.java index 10b7af614..8247ddd53 100644 --- a/src/main/java/com/yelp/nrtsearch/server/luceneserver/warming/ReservoirSampler.java +++ b/src/main/java/com/yelp/nrtsearch/server/luceneserver/warming/ReservoirSampler.java @@ -29,7 +29,9 @@ public class ReservoirSampler { private final long maxQueries; private final AtomicLong numQueries; - /** @param maxQueries Maximum number of warming queries. */ + /** + * @param maxQueries Maximum number of warming queries. + */ public ReservoirSampler(long maxQueries) { this.maxQueries = maxQueries; this.numQueries = new AtomicLong(0); diff --git a/src/main/java/com/yelp/nrtsearch/server/plugins/MetricsPlugin.java b/src/main/java/com/yelp/nrtsearch/server/plugins/MetricsPlugin.java index e924d32a5..456126271 100644 --- a/src/main/java/com/yelp/nrtsearch/server/plugins/MetricsPlugin.java +++ b/src/main/java/com/yelp/nrtsearch/server/plugins/MetricsPlugin.java @@ -23,6 +23,8 @@ */ public interface MetricsPlugin { - /** @param collectorRegistry Nrtsearch Prometheus collector registry. */ + /** + * @param collectorRegistry Nrtsearch Prometheus collector registry. + */ void registerMetrics(CollectorRegistry collectorRegistry); } diff --git a/src/main/java/org/apache/lucene/search/suggest/document/Completion90PostingsFormat.java b/src/main/java/org/apache/lucene/search/suggest/document/Completion90PostingsFormat.java index 76bc144c2..7da2411e9 100644 --- a/src/main/java/org/apache/lucene/search/suggest/document/Completion90PostingsFormat.java +++ b/src/main/java/org/apache/lucene/search/suggest/document/Completion90PostingsFormat.java @@ -26,6 +26,7 @@ */ public class Completion90PostingsFormat extends CompletionPostingsFormat { private static final Logger logger = LoggerFactory.getLogger(Completion90PostingsFormat.class); + /** * Creates a {@link Completion90PostingsFormat} that will load the completion FST based on the * value present in {@link CompletionPostingsFormatUtil}. diff --git a/src/main/java/org/apache/lucene/search/suggest/document/MyContextQuery.java b/src/main/java/org/apache/lucene/search/suggest/document/MyContextQuery.java index e003263c8..4e9cf6629 100644 --- a/src/main/java/org/apache/lucene/search/suggest/document/MyContextQuery.java +++ b/src/main/java/org/apache/lucene/search/suggest/document/MyContextQuery.java @@ -51,6 +51,7 @@ public class MyContextQuery extends ContextQuery { private IntsRefBuilder scratch = new IntsRefBuilder(); private Map contexts; private boolean matchAllContexts = false; + /** Inner completion query */ protected CompletionQuery innerQuery; diff --git a/src/test/java/com/yelp/nrtsearch/clientlib/NodeNameResolverAndLoadBalancingTests.java b/src/test/java/com/yelp/nrtsearch/clientlib/NodeNameResolverAndLoadBalancingTests.java index eea11a3f5..76bd6b4d4 100644 --- a/src/test/java/com/yelp/nrtsearch/clientlib/NodeNameResolverAndLoadBalancingTests.java +++ b/src/test/java/com/yelp/nrtsearch/clientlib/NodeNameResolverAndLoadBalancingTests.java @@ -71,6 +71,7 @@ public class NodeNameResolverAndLoadBalancingTests { * end of test. */ @Rule public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + /** * This rule ensures the temporary folder which maintains indexes are cleaned up after each test */ diff --git a/src/test/java/com/yelp/nrtsearch/server/config/LuceneServerConfigurationTest.java b/src/test/java/com/yelp/nrtsearch/server/config/LuceneServerConfigurationTest.java index e35f447fe..b620159f2 100644 --- a/src/test/java/com/yelp/nrtsearch/server/config/LuceneServerConfigurationTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/config/LuceneServerConfigurationTest.java @@ -19,8 +19,6 @@ import com.yelp.nrtsearch.server.grpc.ReplicationServerClient; import java.io.ByteArrayInputStream; -import java.lang.reflect.Field; -import java.util.Map; import org.apache.lucene.search.suggest.document.CompletionPostingsFormat.FSTLoadMode; import org.junit.Test; @@ -30,20 +28,6 @@ private LuceneServerConfiguration getForConfig(String config) { return new LuceneServerConfiguration(new ByteArrayInputStream(config.getBytes())); } - // A little hacky, but not many option for setting environment variables in a running process - private void setEnv(String key, String value) { - try { - Map env = System.getenv(); - Class cl = env.getClass(); - Field f = cl.getDeclaredField("m"); - f.setAccessible(true); - Map mutableEnv = (Map) f.get(env); - mutableEnv.put(key, value); - } catch (Exception e) { - throw new RuntimeException("Unable to set environment variable", e); - } - } - @Test public void testGetsHostName() { String config = String.join("\n", "nodeName: \"lucene_server_foo\"", "hostName: my_host_name"); @@ -53,7 +37,6 @@ public void testGetsHostName() { @Test public void testGetEnvHostName() { - setEnv("CUSTOM_HOST", "my_custom_host"); String config = String.join("\n", "nodeName: \"lucene_server_foo\"", "hostName: ${CUSTOM_HOST}"); LuceneServerConfiguration luceneConfig = getForConfig(config); @@ -62,8 +45,6 @@ public void testGetEnvHostName() { @Test public void testGetMultiEnvHostName() { - setEnv("VAR1", "v1"); - setEnv("VAR2", "v2"); String config = String.join( "\n", "nodeName: \"lucene_server_foo\"", "hostName: my_${VAR1}_${VAR2}_${VAR1}_host"); @@ -73,7 +54,6 @@ public void testGetMultiEnvHostName() { @Test public void testMissingEnvHostName() { - setEnv("VAR3", "v3"); String config = String.join( "\n", "nodeName: \"lucene_server_foo\"", "hostName: my_${VAR4}_${VAR3}_${VAR4}_host"); diff --git a/src/test/java/com/yelp/nrtsearch/server/grpc/AckedCopyTest.java b/src/test/java/com/yelp/nrtsearch/server/grpc/AckedCopyTest.java index abd003e18..ec94df5ba 100644 --- a/src/test/java/com/yelp/nrtsearch/server/grpc/AckedCopyTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/grpc/AckedCopyTest.java @@ -41,6 +41,7 @@ public class AckedCopyTest { * end of test. */ @Rule public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + /** * This rule ensure the temporary folder which maintains indexes are cleaned up after each test */ diff --git a/src/test/java/com/yelp/nrtsearch/server/grpc/CopyFileTest.java b/src/test/java/com/yelp/nrtsearch/server/grpc/CopyFileTest.java index e23287dab..a665f902b 100644 --- a/src/test/java/com/yelp/nrtsearch/server/grpc/CopyFileTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/grpc/CopyFileTest.java @@ -35,6 +35,7 @@ public class CopyFileTest { private static final int TOTAL_CHUNKS = 10; private static final int CHUNK_SIZE = 1024 * 64; + /** * This rule manages automatic graceful shutdown for the registered servers and channels at the * end of test. diff --git a/src/test/java/com/yelp/nrtsearch/server/grpc/CustomFieldTypeTest.java b/src/test/java/com/yelp/nrtsearch/server/grpc/CustomFieldTypeTest.java index 1022bbaa2..469584639 100644 --- a/src/test/java/com/yelp/nrtsearch/server/grpc/CustomFieldTypeTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/grpc/CustomFieldTypeTest.java @@ -53,6 +53,7 @@ public class CustomFieldTypeTest { * end of test. */ @Rule public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + /** * This rule ensure the temporary folder which maintains indexes are cleaned up after each test */ diff --git a/src/test/java/com/yelp/nrtsearch/server/grpc/LuceneServerIdFieldTest.java b/src/test/java/com/yelp/nrtsearch/server/grpc/LuceneServerIdFieldTest.java index e0ea3ec88..2cab14cce 100644 --- a/src/test/java/com/yelp/nrtsearch/server/grpc/LuceneServerIdFieldTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/grpc/LuceneServerIdFieldTest.java @@ -46,6 +46,7 @@ public class LuceneServerIdFieldTest { * end of test. */ @Rule public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + /** * This rule ensure the temporary folder which maintains indexes are cleaned up after each test */ diff --git a/src/test/java/com/yelp/nrtsearch/server/grpc/LuceneServerTest.java b/src/test/java/com/yelp/nrtsearch/server/grpc/LuceneServerTest.java index a057c7573..bcb8405d9 100644 --- a/src/test/java/com/yelp/nrtsearch/server/grpc/LuceneServerTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/grpc/LuceneServerTest.java @@ -105,6 +105,7 @@ public class LuceneServerTest { * end of test. */ @Rule public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + /** * This rule ensure the temporary folder which maintains indexes are cleaned up after each test */ diff --git a/src/test/java/com/yelp/nrtsearch/server/grpc/MergeBehaviorTests.java b/src/test/java/com/yelp/nrtsearch/server/grpc/MergeBehaviorTests.java index 85147045e..05a98187c 100644 --- a/src/test/java/com/yelp/nrtsearch/server/grpc/MergeBehaviorTests.java +++ b/src/test/java/com/yelp/nrtsearch/server/grpc/MergeBehaviorTests.java @@ -54,6 +54,7 @@ public class MergeBehaviorTests { * end of test. */ @Rule public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + /** * This rule ensure the temporary folder which maintains indexes are cleaned up after each test */ diff --git a/src/test/java/com/yelp/nrtsearch/server/grpc/QueryTest.java b/src/test/java/com/yelp/nrtsearch/server/grpc/QueryTest.java index 1c494b94a..86996a448 100644 --- a/src/test/java/com/yelp/nrtsearch/server/grpc/QueryTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/grpc/QueryTest.java @@ -42,6 +42,7 @@ public class QueryTest { * end of test. */ @Rule public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + /** * This rule ensure the temporary folder which maintains indexes are cleaned up after each test */ diff --git a/src/test/java/com/yelp/nrtsearch/server/grpc/ReplicationServerTest.java b/src/test/java/com/yelp/nrtsearch/server/grpc/ReplicationServerTest.java index 40246ff6b..c8c0415f4 100644 --- a/src/test/java/com/yelp/nrtsearch/server/grpc/ReplicationServerTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/grpc/ReplicationServerTest.java @@ -43,11 +43,13 @@ @RunWith(JUnit4.class) public class ReplicationServerTest { private static final String BUCKET_NAME = "archiver-unittest"; + /** * This rule manages automatic graceful shutdown for the registered servers and channels at the * end of test. */ @Rule public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + /** * This rule ensure the temporary folder which maintains indexes are cleaned up after each test */ diff --git a/src/test/java/com/yelp/nrtsearch/server/grpc/ReplicationTestFailureScenarios.java b/src/test/java/com/yelp/nrtsearch/server/grpc/ReplicationTestFailureScenarios.java index 68386d2fc..48403333c 100644 --- a/src/test/java/com/yelp/nrtsearch/server/grpc/ReplicationTestFailureScenarios.java +++ b/src/test/java/com/yelp/nrtsearch/server/grpc/ReplicationTestFailureScenarios.java @@ -44,11 +44,13 @@ @RunWith(JUnit4.class) public class ReplicationTestFailureScenarios { public static final String TEST_INDEX = "test_index"; + /** * This rule manages automatic graceful shutdown for the registered servers and channels at the * end of test. */ @Rule public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + /** * This rule ensure the temporary folder which maintains stateDir are cleaned up after each test */ diff --git a/src/test/java/com/yelp/nrtsearch/server/grpc/StateBackendServerTest.java b/src/test/java/com/yelp/nrtsearch/server/grpc/StateBackendServerTest.java index 312b18c60..fa49a7f83 100644 --- a/src/test/java/com/yelp/nrtsearch/server/grpc/StateBackendServerTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/grpc/StateBackendServerTest.java @@ -758,8 +758,7 @@ public void testSetIndexSettings() throws IOException { .build()) .build()); IndexSettings expectedSettings = - ImmutableIndexState.DEFAULT_INDEX_SETTINGS - .toBuilder() + ImmutableIndexState.DEFAULT_INDEX_SETTINGS.toBuilder() .setNrtCachingDirectoryMaxSizeMB(DoubleValue.newBuilder().setValue(120.0).build()) .setNrtCachingDirectoryMaxMergeSizeMB(DoubleValue.newBuilder().setValue(60.0).build()) .setIndexMergeSchedulerAutoThrottle(BoolValue.newBuilder().setValue(true).build()) @@ -789,8 +788,7 @@ public void testIndexSettingsPersistRestart() throws IOException { .build()) .build()); IndexSettings expectedSettings = - ImmutableIndexState.DEFAULT_INDEX_SETTINGS - .toBuilder() + ImmutableIndexState.DEFAULT_INDEX_SETTINGS.toBuilder() .setNrtCachingDirectoryMaxSizeMB(DoubleValue.newBuilder().setValue(120.0).build()) .setNrtCachingDirectoryMaxMergeSizeMB(DoubleValue.newBuilder().setValue(60.0).build()) .setIndexMergeSchedulerAutoThrottle(BoolValue.newBuilder().setValue(true).build()) @@ -832,8 +830,7 @@ public void testSetIndexLiveSettings() throws IOException { .build()) .build()); IndexLiveSettings expectedSettings = - ImmutableIndexState.DEFAULT_INDEX_LIVE_SETTINGS - .toBuilder() + ImmutableIndexState.DEFAULT_INDEX_LIVE_SETTINGS.toBuilder() .setDefaultTerminateAfter(Int32Value.newBuilder().setValue(1000).build()) .setSegmentsPerTier(Int32Value.newBuilder().setValue(4).build()) .setSliceMaxSegments(Int32Value.newBuilder().setValue(50).build()) @@ -864,8 +861,7 @@ public void testIndexLiveSettingsPersistRestart() throws IOException { .build()) .build()); IndexLiveSettings expectedSettings = - ImmutableIndexState.DEFAULT_INDEX_LIVE_SETTINGS - .toBuilder() + ImmutableIndexState.DEFAULT_INDEX_LIVE_SETTINGS.toBuilder() .setDefaultTerminateAfter(Int32Value.newBuilder().setValue(1000).build()) .setSegmentsPerTier(Int32Value.newBuilder().setValue(4).build()) .setSliceMaxSegments(Int32Value.newBuilder().setValue(50).build()) @@ -1406,8 +1402,7 @@ public void testSettingsV1Partial() throws IOException { SettingsResponse response = primaryClient.getBlockingStub().settings(request); IndexSettings expectedSettings = - ImmutableIndexState.DEFAULT_INDEX_SETTINGS - .toBuilder() + ImmutableIndexState.DEFAULT_INDEX_SETTINGS.toBuilder() .setNrtCachingDirectoryMaxSizeMB(DoubleValue.newBuilder().setValue(101.0).build()) .setNrtCachingDirectoryMaxMergeSizeMB(DoubleValue.newBuilder().setValue(51.0).build()) .setIndexSort( @@ -1490,8 +1485,7 @@ public void testLiveSettingsV1Partial() throws IOException { LiveSettingsResponse response = primaryClient.getBlockingStub().liveSettings(request); IndexLiveSettings expectedSettings = - ImmutableIndexState.DEFAULT_INDEX_LIVE_SETTINGS - .toBuilder() + ImmutableIndexState.DEFAULT_INDEX_LIVE_SETTINGS.toBuilder() .setMaxRefreshSec(DoubleValue.newBuilder().setValue(30.0).build()) .setMaxSearcherAgeSec(DoubleValue.newBuilder().setValue(120.0).build()) .setIndexRamBufferSizeMB(DoubleValue.newBuilder().setValue(128.0).build()) diff --git a/src/test/java/com/yelp/nrtsearch/server/grpc/SuggestTest.java b/src/test/java/com/yelp/nrtsearch/server/grpc/SuggestTest.java index 7d4a1fa46..050bebfdc 100644 --- a/src/test/java/com/yelp/nrtsearch/server/grpc/SuggestTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/grpc/SuggestTest.java @@ -63,6 +63,7 @@ enum Suggester { * end of test. */ @Rule public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + /** * This rule ensure the temporary folder which maintains indexes are cleaned up after each test */ diff --git a/src/test/java/com/yelp/nrtsearch/server/luceneserver/ServerTestCase.java b/src/test/java/com/yelp/nrtsearch/server/luceneserver/ServerTestCase.java index bea0b0e71..7afaf5641 100644 --- a/src/test/java/com/yelp/nrtsearch/server/luceneserver/ServerTestCase.java +++ b/src/test/java/com/yelp/nrtsearch/server/luceneserver/ServerTestCase.java @@ -67,11 +67,13 @@ */ public class ServerTestCase { public static final String DEFAULT_TEST_INDEX = "test_index"; + /** * This rule manages automatic graceful shutdown for the registered servers and channels at the * end of test. */ @ClassRule public static final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + /** * This rule ensure the temporary folder which maintains indexes are cleaned up after each test */ diff --git a/src/test/java/com/yelp/nrtsearch/server/luceneserver/field/MultivaluedObjectTest.java b/src/test/java/com/yelp/nrtsearch/server/luceneserver/field/MultivaluedObjectTest.java index aedabf79b..6043113ed 100644 --- a/src/test/java/com/yelp/nrtsearch/server/luceneserver/field/MultivaluedObjectTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/luceneserver/field/MultivaluedObjectTest.java @@ -206,8 +206,7 @@ public void testQueryMultipleObjectFields() { BooleanClause.newBuilder() .setOccur(BooleanClause.Occur.SHOULD) .setQuery( - buildTermQuery("multivalued_object.field1", "22") - .toBuilder() + buildTermQuery("multivalued_object.field1", "22").toBuilder() .setBoost(2)) .build()) .addClauses( diff --git a/src/test/java/com/yelp/nrtsearch/server/luceneserver/index/BackendStateManagerTest.java b/src/test/java/com/yelp/nrtsearch/server/luceneserver/index/BackendStateManagerTest.java index 654365cfc..4b1eefc57 100644 --- a/src/test/java/com/yelp/nrtsearch/server/luceneserver/index/BackendStateManagerTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/luceneserver/index/BackendStateManagerTest.java @@ -362,8 +362,7 @@ public void testUpdateEmptySettings() throws IOException { .setNrtCachingDirectoryMaxSizeMB(DoubleValue.newBuilder().setValue(75.0).build()) .build(); IndexSettings expectedMergedSettings = - ImmutableIndexState.DEFAULT_INDEX_SETTINGS - .toBuilder() + ImmutableIndexState.DEFAULT_INDEX_SETTINGS.toBuilder() .setDirectory(StringValue.newBuilder().setValue("MMapDirectory").build()) .setIndexMergeSchedulerAutoThrottle(BoolValue.newBuilder().setValue(true).build()) .setNrtCachingDirectoryMaxSizeMB(DoubleValue.newBuilder().setValue(75.0).build()) @@ -441,8 +440,7 @@ public void testUpdateExistingSettings() throws IOException { .setConcurrentMergeSchedulerMaxMergeCount(Int32Value.newBuilder().setValue(5).build()) .build(); IndexSettings expectedMergedSettings = - ImmutableIndexState.DEFAULT_INDEX_SETTINGS - .toBuilder() + ImmutableIndexState.DEFAULT_INDEX_SETTINGS.toBuilder() .setDirectory(StringValue.newBuilder().setValue("MMapDirectory").build()) .setIndexMergeSchedulerAutoThrottle(BoolValue.newBuilder().setValue(true).build()) .setNrtCachingDirectoryMaxSizeMB(DoubleValue.newBuilder().setValue(75.0).build()) @@ -666,8 +664,7 @@ public void testUpdateEmptyLiveSettings() throws IOException { .setAddDocumentsMaxBufferLen(Int32Value.newBuilder().setValue(250).build()) .build(); IndexLiveSettings expectedMergedSettings = - ImmutableIndexState.DEFAULT_INDEX_LIVE_SETTINGS - .toBuilder() + ImmutableIndexState.DEFAULT_INDEX_LIVE_SETTINGS.toBuilder() .setMaxRefreshSec(DoubleValue.newBuilder().setValue(15.0).build()) .setSliceMaxSegments(Int32Value.newBuilder().setValue(10).build()) .setAddDocumentsMaxBufferLen(Int32Value.newBuilder().setValue(250).build()) @@ -746,8 +743,7 @@ public void testUpdateExistingLiveSettings() throws IOException { .setIndexRamBufferSizeMB(DoubleValue.newBuilder().setValue(512.0).build()) .build(); IndexLiveSettings expectedMergedSettings = - ImmutableIndexState.DEFAULT_INDEX_LIVE_SETTINGS - .toBuilder() + ImmutableIndexState.DEFAULT_INDEX_LIVE_SETTINGS.toBuilder() .setMaxRefreshSec(DoubleValue.newBuilder().setValue(15.0).build()) .setAddDocumentsMaxBufferLen(Int32Value.newBuilder().setValue(250).build()) .setSliceMaxSegments(Int32Value.newBuilder().setValue(3).build()) @@ -841,8 +837,7 @@ public void testUpdateFields() throws IOException { .build()); IndexStateInfo expectedState = - initialState - .toBuilder() + initialState.toBuilder() .setGen(1) .putFields("field1", addFields.get(0)) .putFields("field2", addFields.get(1)) @@ -939,8 +934,7 @@ public void testUpdateFieldsAddToExisting() throws IOException { .build()); IndexStateInfo expectedState = - initialState - .toBuilder() + initialState.toBuilder() .setGen(1) .putFields("field3", addFields.get(0)) .putFields("field4", addFields.get(1)) diff --git a/src/test/java/com/yelp/nrtsearch/server/luceneserver/index/ImmutableIndexStateTest.java b/src/test/java/com/yelp/nrtsearch/server/luceneserver/index/ImmutableIndexStateTest.java index 9c7b58e4b..bedc07077 100644 --- a/src/test/java/com/yelp/nrtsearch/server/luceneserver/index/ImmutableIndexStateTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/luceneserver/index/ImmutableIndexStateTest.java @@ -801,8 +801,7 @@ public void testGetMergedSettings() throws IOException { .build(); ImmutableIndexState indexState = getIndexState(getStateWithSettings(settings)); IndexSettings expectedMergedSettings = - ImmutableIndexState.DEFAULT_INDEX_SETTINGS - .toBuilder() + ImmutableIndexState.DEFAULT_INDEX_SETTINGS.toBuilder() .setConcurrentMergeSchedulerMaxMergeCount(wrap(5)) .setConcurrentMergeSchedulerMaxThreadCount(wrap(2)) .setNrtCachingDirectoryMaxSizeMB(wrap(100.0)) @@ -820,8 +819,7 @@ public void testGetMergedLiveSettings() throws IOException { .build(); ImmutableIndexState indexState = getIndexState(getStateWithLiveSettings(liveSettings)); IndexLiveSettings expectedMergedSettings = - ImmutableIndexState.DEFAULT_INDEX_LIVE_SETTINGS - .toBuilder() + ImmutableIndexState.DEFAULT_INDEX_LIVE_SETTINGS.toBuilder() .setDefaultTerminateAfter(wrap(100)) .setMaxRefreshSec(wrap(10.0)) .setSegmentsPerTier(wrap(5)) @@ -1443,8 +1441,7 @@ public void testGetSaveState_liveSettings() throws IOException { @Test public void testGetSaveState_fields() throws IOException { IndexStateInfo stateInfo = - getEmptyState() - .toBuilder() + getEmptyState().toBuilder() .putFields( "field1", Field.newBuilder() diff --git a/src/test/java/com/yelp/nrtsearch/server/luceneserver/script/ScoreScriptTest.java b/src/test/java/com/yelp/nrtsearch/server/luceneserver/script/ScoreScriptTest.java index bbe2f4894..33aeb54a2 100644 --- a/src/test/java/com/yelp/nrtsearch/server/luceneserver/script/ScoreScriptTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/luceneserver/script/ScoreScriptTest.java @@ -71,6 +71,7 @@ public class ScoreScriptTest { * end of test. */ @Rule public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + /** * This rule ensure the temporary folder which maintains indexes are cleaned up after each test */ diff --git a/src/test/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/CollectorTest.java b/src/test/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/CollectorTest.java index 7b97d4a75..016968d9e 100644 --- a/src/test/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/CollectorTest.java +++ b/src/test/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/CollectorTest.java @@ -395,8 +395,12 @@ public void testCustomCollector() throws InvalidProtocolBufferException { "7", 93.0, "8", 92.0); Map collectedHits = - collectorsResult.get(COLLECTOR_NAME).getAnyResult().unpack(SearchResponse.class) - .getHitsList().stream() + collectorsResult + .get(COLLECTOR_NAME) + .getAnyResult() + .unpack(SearchResponse.class) + .getHitsList() + .stream() .collect( Collectors.toMap( hit -> hit.getFieldsMap().get("review_id").getFieldValue(0).getTextValue(), diff --git a/src/test/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/additional/TermsCollectorManagerTestsBase.java b/src/test/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/additional/TermsCollectorManagerTestsBase.java index d479c7891..7c0c9c7c8 100644 --- a/src/test/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/additional/TermsCollectorManagerTestsBase.java +++ b/src/test/java/com/yelp/nrtsearch/server/luceneserver/search/collectors/additional/TermsCollectorManagerTestsBase.java @@ -494,16 +494,14 @@ void testOrderByNestedCollector() { void testOrderByNestedCollector(TermsCollector terms) { terms = - terms - .toBuilder() + terms.toBuilder() .setOrder(BucketOrder.newBuilder().setKey("nested").setOrder(OrderType.DESC).build()) .build(); SearchResponse response = doNestedOrderQuery(terms); assertNestedOrderResult(response, 8, 8, 0, EXPECTED_WITH_NESTED_DESC); terms = - terms - .toBuilder() + terms.toBuilder() .setOrder(BucketOrder.newBuilder().setKey("nested").setOrder(OrderType.ASC).build()) .build(); response = doNestedOrderQuery(terms); diff --git a/src/test/java/com/yelp/nrtsearch/tools/nrt_utils/state/PutRemoteStateCommandTest.java b/src/test/java/com/yelp/nrtsearch/tools/nrt_utils/state/PutRemoteStateCommandTest.java index 8944695ea..725690490 100644 --- a/src/test/java/com/yelp/nrtsearch/tools/nrt_utils/state/PutRemoteStateCommandTest.java +++ b/src/test/java/com/yelp/nrtsearch/tools/nrt_utils/state/PutRemoteStateCommandTest.java @@ -125,8 +125,7 @@ public void testPutIndexState() throws IOException { ((ImmutableIndexState) server.getGlobalState().getIndex("test_index")) .getCurrentStateInfo(); IndexStateInfo updatedState = - currentState - .toBuilder() + currentState.toBuilder() .setLiveSettings( IndexLiveSettings.newBuilder() .setSliceMaxSegments(Int32Value.newBuilder().setValue(1).build()) @@ -160,8 +159,7 @@ public void testPutIndexStateExact() throws IOException { ((ImmutableIndexState) server.getGlobalState().getIndex("test_index")) .getCurrentStateInfo(); IndexStateInfo updatedState = - currentState - .toBuilder() + currentState.toBuilder() .setLiveSettings( IndexLiveSettings.newBuilder() .setSliceMaxSegments(Int32Value.newBuilder().setValue(1).build()) diff --git a/src/test/java/com/yelp/nrtsearch/tools/nrt_utils/state/StateCommandUtilsTest.java b/src/test/java/com/yelp/nrtsearch/tools/nrt_utils/state/StateCommandUtilsTest.java index 36de2f8ef..7cca5fb8e 100644 --- a/src/test/java/com/yelp/nrtsearch/tools/nrt_utils/state/StateCommandUtilsTest.java +++ b/src/test/java/com/yelp/nrtsearch/tools/nrt_utils/state/StateCommandUtilsTest.java @@ -230,8 +230,7 @@ public void testWriteStateDataToBackend_IndexState() throws IOException { ((ImmutableIndexState) server.getGlobalState().getIndex("test_index")) .getCurrentStateInfo(); IndexStateInfo updatedState = - currentState - .toBuilder() + currentState.toBuilder() .setLiveSettings( IndexLiveSettings.newBuilder() .setSliceMaxSegments(Int32Value.newBuilder().setValue(1).build())