diff --git a/.github/workflows/java-benchmark.yml b/.github/workflows/java-benchmark.yml new file mode 100644 index 0000000000..68461e789b --- /dev/null +++ b/.github/workflows/java-benchmark.yml @@ -0,0 +1,43 @@ +name: Java client benchmarks + +on: + workflow_dispatch: + inputs: + name: + required: false + type: string + +run-name: ${{ inputs.name == '' && format('{0} @ {1}', github.ref_name, github.sha) || inputs.name }} + +jobs: + java-benchmark: + strategy: + matrix: + java: + - 11 + - 17 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set up JDK ${{ matrix.java }} + uses: actions/setup-java@v3 + with: + distribution: "temurin" + java-version: ${{ matrix.java }} + + - name: Run benchmarks + working-directory: java/jabushka + run: ./gradlew -Pbenchmark build + + - name: Upload test reports + if: always() + continue-on-error: true + uses: actions/upload-artifact@v3 + with: + name: test-reports-${{ matrix.java }} + path: | + java/jabushka/benchmarks/build/reports/** diff --git a/.github/workflows/java.yml b/.github/workflows/java.yml new file mode 100644 index 0000000000..4839d39d4d --- /dev/null +++ b/.github/workflows/java.yml @@ -0,0 +1,59 @@ +name: SQL Java CI + +on: + pull_request: + push: + paths: + - "java/**" + - ".github/workflows/java.yml" + +# Run only most latest job on a branch and cancel previous ones +concurrency: + group: ${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + build-and-test-java-client: + strategy: + # Run all jobs + fail-fast: false + matrix: + java: + - 11 + - 17 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set up JDK ${{ matrix.java }} + uses: actions/setup-java@v3 + with: + distribution: "temurin" + java-version: ${{ matrix.java }} + + - name: Install and run protoc (protobuf) + run: | + sudo apt update + sudo apt install -y protobuf-compiler + protoc -Iprotobuf=babushka-core/src/protobuf/ --java_out=java/jabushka/jabushka/src/main/java/org/babushka/jabushka/generated babushka-core/src/protobuf/*.proto + + - name: Build rust part + working-directory: java + run: cargo build + + - name: Build with Gradle + working-directory: java/jabushka + run: ./gradlew --continue build + + - name: Upload test reports + if: always() + continue-on-error: true + uses: actions/upload-artifact@v3 + with: + name: test-reports-${{ matrix.java }} + path: | + java/jabushka/jabushka/build/reports/** + java/jabushka/integTest/build/reports/** diff --git a/.gitignore b/.gitignore index 92ac3aaf47..ad4f5014ba 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ debug/ target/ +# Git stuff +.worktrees + # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html Cargo.lock @@ -17,6 +20,14 @@ dump.rdb .env benchmarks/results +# IDE generaged files +.vs +.vscode +.idea + +# MacOS metadata +.DS_Store + # lock files yarn.lock diff --git a/java/.cargo/config.toml b/java/.cargo/config.toml new file mode 100644 index 0000000000..24a6f21533 --- /dev/null +++ b/java/.cargo/config.toml @@ -0,0 +1,3 @@ +[env] +BABUSHKA_NAME = { value = "BabushkaPy", force = true } +BABUSHKA_VERSION = "0.1.0" diff --git a/java/.gitignore b/java/.gitignore index 1b6985c009..8f60484e5a 100644 --- a/java/.gitignore +++ b/java/.gitignore @@ -3,3 +3,6 @@ # Ignore Gradle build output directory build + +# Ignore generated files (e.g. protobuf) +generated diff --git a/java/Cargo.toml b/java/Cargo.toml new file mode 100644 index 0000000000..ccde88c26d --- /dev/null +++ b/java/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "jabushka" +version = "0.0.0" +edition = "2021" +license = "BSD-3-Clause" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "jabushka" +crate-type = ["cdylib"] + +[dependencies] +redis = { path = "../submodules/redis-rs/redis", features = ["aio", "tokio-comp", "connection-manager", "tls", "tokio-rustls-comp"] } +babushka = { path = "../babushka-core" } +tokio = { version = "^1", features = ["rt", "macros", "rt-multi-thread", "time"] } +logger_core = {path = "../logger_core"} +tracing-subscriber = "0.3.16" + +[profile.release] +lto = true +debug = true diff --git a/java/benchmarks/build.gradle b/java/jabushka/benchmarks/build.gradle similarity index 100% rename from java/benchmarks/build.gradle rename to java/jabushka/benchmarks/build.gradle diff --git a/java/benchmarks/src/main/java/javabushka/client/BenchmarkingApp.java b/java/jabushka/benchmarks/src/main/java/javabushka/client/BenchmarkingApp.java similarity index 100% rename from java/benchmarks/src/main/java/javabushka/client/BenchmarkingApp.java rename to java/jabushka/benchmarks/src/main/java/javabushka/client/BenchmarkingApp.java diff --git a/java/benchmarks/src/main/java/javabushka/client/jedis/JedisClient.java b/java/jabushka/benchmarks/src/main/java/javabushka/client/jedis/JedisClient.java similarity index 100% rename from java/benchmarks/src/main/java/javabushka/client/jedis/JedisClient.java rename to java/jabushka/benchmarks/src/main/java/javabushka/client/jedis/JedisClient.java diff --git a/java/benchmarks/src/main/java/javabushka/client/lettuce/LettuceAsyncClient.java b/java/jabushka/benchmarks/src/main/java/javabushka/client/lettuce/LettuceAsyncClient.java similarity index 100% rename from java/benchmarks/src/main/java/javabushka/client/lettuce/LettuceAsyncClient.java rename to java/jabushka/benchmarks/src/main/java/javabushka/client/lettuce/LettuceAsyncClient.java diff --git a/java/benchmarks/src/main/java/javabushka/client/lettuce/LettuceClient.java b/java/jabushka/benchmarks/src/main/java/javabushka/client/lettuce/LettuceClient.java similarity index 100% rename from java/benchmarks/src/main/java/javabushka/client/lettuce/LettuceClient.java rename to java/jabushka/benchmarks/src/main/java/javabushka/client/lettuce/LettuceClient.java diff --git a/java/benchmarks/src/main/java/javabushka/client/utils/Benchmarking.java b/java/jabushka/benchmarks/src/main/java/javabushka/client/utils/Benchmarking.java similarity index 100% rename from java/benchmarks/src/main/java/javabushka/client/utils/Benchmarking.java rename to java/jabushka/benchmarks/src/main/java/javabushka/client/utils/Benchmarking.java diff --git a/java/benchmarks/src/main/java/javabushka/client/utils/ChosenAction.java b/java/jabushka/benchmarks/src/main/java/javabushka/client/utils/ChosenAction.java similarity index 100% rename from java/benchmarks/src/main/java/javabushka/client/utils/ChosenAction.java rename to java/jabushka/benchmarks/src/main/java/javabushka/client/utils/ChosenAction.java diff --git a/java/benchmarks/src/main/java/javabushka/client/utils/LatencyResults.java b/java/jabushka/benchmarks/src/main/java/javabushka/client/utils/LatencyResults.java similarity index 100% rename from java/benchmarks/src/main/java/javabushka/client/utils/LatencyResults.java rename to java/jabushka/benchmarks/src/main/java/javabushka/client/utils/LatencyResults.java diff --git a/java/benchmarks/src/test/java/javabushka/client/jedis/JedisClientIT.java b/java/jabushka/benchmarks/src/test/java/javabushka/client/jedis/JedisClientIT.java similarity index 100% rename from java/benchmarks/src/test/java/javabushka/client/jedis/JedisClientIT.java rename to java/jabushka/benchmarks/src/test/java/javabushka/client/jedis/JedisClientIT.java diff --git a/java/benchmarks/src/test/java/javabushka/client/lettuce/LettuceAsyncClientIT.java b/java/jabushka/benchmarks/src/test/java/javabushka/client/lettuce/LettuceAsyncClientIT.java similarity index 100% rename from java/benchmarks/src/test/java/javabushka/client/lettuce/LettuceAsyncClientIT.java rename to java/jabushka/benchmarks/src/test/java/javabushka/client/lettuce/LettuceAsyncClientIT.java diff --git a/java/benchmarks/src/test/java/javabushka/client/lettuce/LettuceClientIT.java b/java/jabushka/benchmarks/src/test/java/javabushka/client/lettuce/LettuceClientIT.java similarity index 100% rename from java/benchmarks/src/test/java/javabushka/client/lettuce/LettuceClientIT.java rename to java/jabushka/benchmarks/src/test/java/javabushka/client/lettuce/LettuceClientIT.java diff --git a/java/jabushka/build.gradle b/java/jabushka/build.gradle new file mode 100644 index 0000000000..dee70654a6 --- /dev/null +++ b/java/jabushka/build.gradle @@ -0,0 +1,102 @@ +plugins { + id 'java' + id 'java-library' + id 'io.freefair.lombok' version '6.4.0' + id 'jacoco' + id 'com.diffplug.spotless' version '6.19.0' +} + +repositories { + mavenCentral() + mavenLocal() +} + +subprojects { + repositories { + mavenCentral() + mavenLocal() + } + // minimal java compatibility level + plugins.withId('java') { + sourceCompatibility = targetCompatibility = "11" + } + tasks.withType(Test) { + useJUnitPlatform() + + testLogging { + exceptionFormat "full" + events "started", "skipped", "passed", "failed" + showStandardStreams true + } + // Temporary suspend jacoco + // finalizedBy jacocoTestReport, jacocoTestCoverageVerification + } +} + +dependencies { + testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.6.2' +} + +// Apply a specific Java toolchain to ease working on different environments. +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +// JaCoCo section (code coverage by unit tests) +jacoco { + toolVersion = "0.8.9" +} +jacocoTestReport { + reports { + xml.configure { enabled false } + csv.configure { enabled false } + } + afterEvaluate { + classDirectories.setFrom(files(classDirectories.files.collect { + fileTree(dir: it) + })) + } +} +jacocoTestCoverageVerification { + violationRules { + rule { + element = 'CLASS' + excludes = [ + ] + limit { + counter = 'LINE' + minimum = 1.0 + } + limit { + counter = 'BRANCH' + minimum = 1.0 + } + } + } + afterEvaluate { + classDirectories.setFrom(files(classDirectories.files.collect { + fileTree(dir: it) + })) + } +} +// Temporary suspend jacoco +// check.dependsOn jacocoTestCoverageVerification +// End of JaCoCo section + +// Spotless section (code style) +spotless { + java { + target fileTree('.') { + include '**/*.java' + exclude '**/build/**', '**/build-*/**', '**/generated/**' + } + importOrder() + removeUnusedImports() + trimTrailingWhitespace() + endWithNewline() + googleJavaFormat('1.17.0').reflowLongStrings().groupArtifact('com.google.googlejavaformat:google-java-format') + } +} +// End of Spotless section diff --git a/java/jabushka/gradle.properties b/java/jabushka/gradle.properties new file mode 100644 index 0000000000..3013c32a31 --- /dev/null +++ b/java/jabushka/gradle.properties @@ -0,0 +1,2 @@ +version=1.13.0 +org.gradle.jvmargs=-Duser.language=en -Duser.country=US diff --git a/java/gradle/wrapper/gradle-wrapper.jar b/java/jabushka/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from java/gradle/wrapper/gradle-wrapper.jar rename to java/jabushka/gradle/wrapper/gradle-wrapper.jar diff --git a/java/gradle/wrapper/gradle-wrapper.properties b/java/jabushka/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from java/gradle/wrapper/gradle-wrapper.properties rename to java/jabushka/gradle/wrapper/gradle-wrapper.properties diff --git a/java/gradlew b/java/jabushka/gradlew similarity index 100% rename from java/gradlew rename to java/jabushka/gradlew diff --git a/java/gradlew.bat b/java/jabushka/gradlew.bat old mode 100644 new mode 100755 similarity index 96% rename from java/gradlew.bat rename to java/jabushka/gradlew.bat index 6689b85bee..93e3f59f13 --- a/java/gradlew.bat +++ b/java/jabushka/gradlew.bat @@ -1,92 +1,92 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -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" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -: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 %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +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" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +: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 %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/java/jabushka/integTest/build.gradle b/java/jabushka/integTest/build.gradle new file mode 100644 index 0000000000..e69de29bb2 diff --git a/java/jabushka/jabushka/build.gradle b/java/jabushka/jabushka/build.gradle new file mode 100644 index 0000000000..f4af267466 --- /dev/null +++ b/java/jabushka/jabushka/build.gradle @@ -0,0 +1,11 @@ +plugins { + id 'java-library' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation group: 'com.google.protobuf', name: 'protobuf-java', version: '3.24.3' +} diff --git a/java/jabushka/jabushka/src/main/java/org/babushka/jabushka/generated/README b/java/jabushka/jabushka/src/main/java/org/babushka/jabushka/generated/README new file mode 100644 index 0000000000..4c40ff15a5 --- /dev/null +++ b/java/jabushka/jabushka/src/main/java/org/babushka/jabushka/generated/README @@ -0,0 +1,2 @@ +Directory for protoc (protobuf) generated files. + diff --git a/java/jabushka/settings.gradle b/java/jabushka/settings.gradle new file mode 100644 index 0000000000..901c56c17e --- /dev/null +++ b/java/jabushka/settings.gradle @@ -0,0 +1,9 @@ +rootProject.name = 'babushka' + +include 'jabushka' +include 'integTest' + +// Run benchmarking by adding `-Pbenchmark` switch to gradlew command line +if (hasProperty('benchmark')) { + include 'benchmarks' +} diff --git a/java/lib/build.gradle b/java/lib/build.gradle deleted file mode 100644 index cc06cd1213..0000000000 --- a/java/lib/build.gradle +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file was generated by the Gradle 'init' task. - * - * This generated file contains a sample Java library project to get you started. - * For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.3/userguide/building_java_projects.html in the Gradle documentation. - */ - -plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' -} - -repositories { - // Use Maven Central for resolving dependencies. - mavenCentral() -} - -dependencies { - // Use JUnit test framework. - testImplementation 'junit:junit:4.13.2' - - // This dependency is exported to consumers, that is to say found on their compile classpath. - api 'org.apache.commons:commons-math3:3.6.1' - - // This dependency is used internally, and not exposed to consumers on their own compile classpath. - implementation 'com.google.guava:guava:32.1.1-jre' -} - -// Apply a specific Java toolchain to ease working on different environments. -java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } -} diff --git a/java/lib/src/main/java/javabushka/Library.java b/java/lib/src/main/java/javabushka/Library.java deleted file mode 100644 index ff87ce99ce..0000000000 --- a/java/lib/src/main/java/javabushka/Library.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * This Java source file was generated by the Gradle 'init' task. - */ -package javabushka; - -public class Library { - public boolean someLibraryMethod() { - return true; - } -} diff --git a/java/lib/src/test/java/javabushka/LibraryTest.java b/java/lib/src/test/java/javabushka/LibraryTest.java deleted file mode 100644 index 0676a72ab8..0000000000 --- a/java/lib/src/test/java/javabushka/LibraryTest.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * This Java source file was generated by the Gradle 'init' task. - */ -package javabushka; - -import org.junit.Test; -import static org.junit.Assert.*; - -public class LibraryTest { - @Test public void someLibraryMethodReturnsTrue() { - Library classUnderTest = new Library(); - assertTrue("someLibraryMethod should return 'true'", classUnderTest.someLibraryMethod()); - } -} diff --git a/java/settings.gradle b/java/settings.gradle deleted file mode 100644 index f4ab308fd0..0000000000 --- a/java/settings.gradle +++ /dev/null @@ -1,15 +0,0 @@ -/* - * This file was generated by the Gradle 'init' task. - * - * The settings file is used to specify which projects to include in your build. - * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.3/userguide/building_swift_projects.html in the Gradle documentation. - */ - -plugins { - // Apply the foojay-resolver plugin to allow automatic download of JDKs - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0' -} - -rootProject.name = 'javabushka' -include('lib') -include('benchmarks') diff --git a/java/src/lib.rs b/java/src/lib.rs new file mode 100644 index 0000000000..e69de29bb2