Skip to content

Commit

Permalink
Create java client project
Browse files Browse the repository at this point in the history
Signed-off-by: acarbonetto <[email protected]>
  • Loading branch information
acarbonetto committed Oct 3, 2023
1 parent 131efa4 commit 0c14076
Show file tree
Hide file tree
Showing 17 changed files with 748 additions and 0 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/java-benchmark.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
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: Start Redis
run: docker run -p 6379:6379 -p 8001:8001 -d redis/redis-stack

- name: Run benchmarks
working-directory: java
run: ./gradlew :benchmark:run

- name: Upload test reports
if: always()
continue-on-error: true
uses: actions/upload-artifact@v3
with:
name: test-reports-${{ matrix.java }}
path: |
java/benchmarks/build/reports/**
62 changes: 62 additions & 0 deletions .github/workflows/java.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: 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
mkdir -p java/client/src/main/java/org/babushka/javababushka/generated
protoc -Iprotobuf=babushka-core/src/protobuf/ --java_out=java/client/src/main/java/org/babushka/javababushka/generated babushka-core/src/protobuf/*.proto
- name: Build rust part
working-directory: java
run: cargo build

- name: Start Redis
run: docker run -p 6379:6379 -p 8001:8001 -d redis/redis-stack

- name: Build java part
working-directory: java
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/client/build/reports/**
java/integTest/build/reports/**
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -17,6 +20,14 @@ dump.rdb
.env
benchmarks/results

# IDE generaged files
.vs
.vscode
.idea

# MacOS metadata
.DS_Store

# lock files

yarn.lock
Expand Down
4 changes: 4 additions & 0 deletions java/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[env]
BABUSHKA_NAME = { value = "javababushka", force = true }
BABUSHKA_VERSION = "0.1.0"

8 changes: 8 additions & 0 deletions java/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Ignore Gradle project-specific cache directory
.gradle

# Ignore Gradle build output directory
build

# Ignore generated files (e.g. protobuf)
generated
22 changes: 22 additions & 0 deletions java/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

[package]
name = "javababushka"
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 = "javababushka"
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
49 changes: 49 additions & 0 deletions java/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Summary - Java Wrapper

This module contains a Java-client wrapper that connects to the `Babushka`-rust-client. The rust client connects to
redis, while this wrapper provides Java-language binding. The objective of this wrapper is to provide a thin-wrapper
language api to enhance performance and limit cpu cycles at scale.

## Organization

The Java client (javababushka) contains the following parts:

1. A Java client (lib folder): wrapper to rust-client
2. An examples script: to sanity test javababushka and similar java-clients against a redis host
3. A benchmark app: to performance benchmark test javababushka and similar java-clients against a redis host

## Building

You can assemble the Java clients benchmarks by compiling using `./gradlew build`.

## Code style

Code style is enforced by spotless with Google Java Format. The build fails if code formatted incorrectly, but you can auto-format code with `./gradlew spotlessApply`.
Run this command before every commit to keep code in the same style.
These IDE plugins can auto-format code on file save or by single click:
* [For Intellij IDEA](https://plugins.jetbrains.com/plugin/18321-spotless-gradle)
* [For VS Code](https://marketplace.visualstudio.com/items?itemName=richardwillis.vscode-spotless-gradle)

## Benchmarks

You can run benchmarks using `./gradlew run`. You can set arguments using the args flag like:

```shell
./gradlew run --args="--clients lettuce"
```

The following arguments are accepted:
* `configuration`: Release or Debug configuration
* `resultsFile`: the results output file
* `concurrentTasks`: Number of concurrent tasks
* `clients`: one of: all|jedis|lettuce|babushka
* `clientCount`: Client count
* `host`: redis server host url
* `port`: redis server port number
* `tls`: redis TLS configured

### Troubleshooting

* If you're unable to connect to redis (such as timeout), check your port or the TLS flag
* Only server-side certificates are supported by the TLS configured redis

41 changes: 41 additions & 0 deletions java/benchmarks/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
plugins {
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
}

repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}

dependencies {
// Use JUnit test framework.
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'

// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:32.1.1-jre'
implementation 'redis.clients:jedis:4.4.3'
implementation 'io.lettuce:lettuce-core:6.2.6.RELEASE'
implementation 'commons-cli:commons-cli:1.5.0'
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.13.0'
}

// Apply a specific Java toolchain to ease working on different environments.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

application {
// Define the main class for the application.
mainClass = 'javababushka.benchmarks.BenchmarkingApp'
}

tasks.withType(Test) {
testLogging {
exceptionFormat "full"
events "started", "skipped", "passed", "failed"
showStandardStreams true
}
}
101 changes: 101 additions & 0 deletions java/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
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()
}

subprojects {
repositories {
mavenCentral()
}
// minimal java compatibility level
plugins.withId('java') {
sourceCompatibility = targetCompatibility = "11"
}
tasks.withType(Test) {
useJUnitPlatform()

testLogging {
exceptionFormat "full"
events "started", "skipped", "passed", "failed"
showStandardStreams true
}
// TODO: add jacoco with code coverage
// finalizedBy jacocoTestReport, jacocoTestCoverageVerification
}
}

dependencies {
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.9.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)
}))
}
}
// TODO: add jacoco with code coverage
// 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

Loading

0 comments on commit 0c14076

Please sign in to comment.