diff --git a/.github/workflows/pcgcli-main.yml b/.github/workflows/pcgcli-main.yml deleted file mode 100644 index 003b2e5..0000000 --- a/.github/workflows/pcgcli-main.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Partitioned Consumer Groups CLI Main Snapshot - -on: - push: - branches: - - main - paths: - - 'pcgroups-cli/**' - -jobs: - build: - runs-on: ubuntu-latest - defaults: - run: - working-directory: ./pcgroups-cli - steps: - - name: Set up JDK - uses: actions/setup-java@v5 - with: - java-version: '21' - distribution: 'temurin' - - name: Check out code - uses: actions/checkout@v4 - - name: Build with Gradle - run: | - chmod +x gradlew && ./gradlew clean test uberJar - - name: Build with Maven - run: mvn clean package - - name: Validate Gradle Uber was created - run: | - FILE_PATH="build/libs/cg.jar" - if [ -f "$FILE_PATH" ]; then - echo "Validation successful: $FILE_PATH was created." - else - echo "Validation failed: $FILE_PATH was not found." - exit 1 # Fails the workflow step - fi - - name: Validate Maven Uber was created - run: | - FILE_PATH="target/cg.jar" - if [ -f "$FILE_PATH" ]; then - echo "Validation successful: $FILE_PATH was created." - else - echo "Validation failed: $FILE_PATH was not found." - exit 1 # Fails the workflow step - fi diff --git a/.github/workflows/pcgcli-pr.yml b/.github/workflows/pcgcli.yml similarity index 57% rename from .github/workflows/pcgcli-pr.yml rename to .github/workflows/pcgcli.yml index b91da6b..569c145 100644 --- a/.github/workflows/pcgcli-pr.yml +++ b/.github/workflows/pcgcli.yml @@ -1,6 +1,9 @@ -name: Partitioned Consumer Groups CLI Pull Request +name: Partitioned Consumer Groups CLI Build on: + push: + branches: + - main pull_request: types: [opened, synchronize, reopened] paths: @@ -21,21 +24,32 @@ jobs: - name: Check out code uses: actions/checkout@v4 - name: Build with Gradle - run: | - chmod +x gradlew && ./gradlew clean test uberJar + run: chmod +x gradlew && ./gradlew clean dist - name: Build with Maven run: mvn clean package - - name: Validate Gradle Uber was created + - name: Validate artifacts were created run: | - FILE_PATH="build/libs/cg.jar" + FILE_PATH="build/cg.jar" + if [ -f "$FILE_PATH" ]; then + echo "Validation successful: $FILE_PATH was created." + else + echo "Validation failed: $FILE_PATH was not found." + exit 1 # Fails the workflow step + fi + FILE_PATH="build/cg.zip" + if [ -f "$FILE_PATH" ]; then + echo "Validation successful: $FILE_PATH was created." + else + echo "Validation failed: $FILE_PATH was not found." + exit 1 # Fails the workflow step + fi + FILE_PATH="build/cg.tar" if [ -f "$FILE_PATH" ]; then echo "Validation successful: $FILE_PATH was created." else echo "Validation failed: $FILE_PATH was not found." exit 1 # Fails the workflow step fi - - name: Validate Maven Uber was created - run: | FILE_PATH="target/cg.jar" if [ -f "$FILE_PATH" ]; then echo "Validation successful: $FILE_PATH was created." diff --git a/pcgroups-cli/README.md b/pcgroups-cli/README.md new file mode 100644 index 0000000..52014c5 --- /dev/null +++ b/pcgroups-cli/README.md @@ -0,0 +1,82 @@ +Orbit + +# Partitioned Consumer Groups CLI + +The Partitioned Consumer Groups CLI is a command line tool. In the usage, + +`cg` stands for `java -jar /cg.jar` + +``` +Usage: cg [options] + +Commands: + static Static consumer groups mode + elastic Elastic consumer groups mode + +Use 'cg --help' for more information about a command. +``` + +``` +Usage: cg static [COMMAND] +Static consumer groups mode +Commands: + ls, list List static consumer groups for a stream + info Get static consumer group info + create Create a static partitioned consumer group + delete, rm Delete a static partitioned consumer group + member-info, memberinfo, minfo Get static consumer group member info + step-down, stepdown, sd Initiate a step down for a member + consume, join Join a static partitioned consumer group + prompt Interactive prompt mode +``` + +``` +Usage: cg elastic [COMMAND] +Elastic consumer groups mode +Commands: + ls, list List elastic consumer groups for a stream + info Get elastic consumer group info + create Create an elastic partitioned consumer + group + delete, rm Delete an elastic partitioned consumer + group + add Add members to an elastic consumer group + drop Drop members from an elastic consumer group + create-mapping, cm, createmapping Create member mappings for an elastic + consumer group + delete-mapping, dm, deletemapping Delete member mappings for an elastic + consumer group + member-info, memberinfo, minfo Get elastic consumer group member info + step-down, stepdown, sd Initiate a step down for a member + consume, join Join an elastic partitioned consumer group + prompt Interactive prompt mode +``` + +## Building from Source +The project contains both a Maven pom.xml file and a Gradle project, +and both are configured to build an executable Java jar named `cg.jar` + +### Maven +``` +mvn clean package +``` + +will build the `cg.jar` in the `target` folder + +### Gradle +``` +gradle clean package +``` +will build the `cg.jar` in the `build` folder + +## Running + + +``` +java -jar target/cg.jar ... +java -jar build/cg.jar ... +``` + +--- +Copyright (c) 2025 Synadia Communications Inc. All Rights Reserved. +See [LICENSE](LICENSE) and [NOTICE](NOTICE) file for details. diff --git a/pcgroups-cli/build.gradle b/pcgroups-cli/build.gradle index 91d173f..094794d 100644 --- a/pcgroups-cli/build.gradle +++ b/pcgroups-cli/build.gradle @@ -1,17 +1,10 @@ plugins { id("java") - id("java-library") - id("maven-publish") - id("jacoco") - id("biz.aQute.bnd.builder") version "7.1.0" - id("org.gradle.test-retry") version "1.6.4" - id("io.github.gradle-nexus.publish-plugin") version "2.0.0" - id("signing") + id 'com.github.johnrengelman.shadow' version '8.1.1' // Apply the shadow plugin } -group = 'io.synadia' version = "0.1.0" -def originalUber = 'pcg-cli-' + version + '-uber.jar' +def originalShadow = 'pcg-cli-' + version + '-all.jar' java { sourceCompatibility = JavaVersion.VERSION_1_8 @@ -27,7 +20,7 @@ repositories { dependencies { implementation 'io.nats:jnats:2.25.1' implementation 'org.jspecify:jspecify:1.0.0' - implementation 'io.synadia:pcgroups:0.1.0-SNAPSHOT' + implementation 'io.synadia:pcgroups:0.1.0' implementation 'info.picocli:picocli:4.7.5' testImplementation 'io.nats:jnats-server-runner:3.1.0' @@ -35,36 +28,39 @@ dependencies { testImplementation 'org.junit.platform:junit-platform-launcher:1.14.3' } -tasks.register('copyToLib', Copy) { - into "build/libs" - from configurations.runtimeClasspath +shadowJar { + manifest { + attributes 'Main-Class': 'io.synadia.pcg.cli.CgCommand' + } } -tasks.register('packageUberJar', Jar) { - archiveClassifier = 'uber' +tasks.register('package', Copy) { + dependsOn shadowJar - from sourceSets.main.output + // we want the file to be called cg.jar + from ('build/libs') + include originalShadow + destinationDir file('build/') + rename originalShadow, "cg.jar" +} - dependsOn configurations.runtimeClasspath - from { - configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) } - } +tasks.register('createZip', Zip) { + dependsOn 'package' - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - dependsOn copyToLib + archiveFileName = "cg.zip" + destinationDirectory = file('build/') + from (files('build/cg.jar')) } -tasks.register('uberJar', Copy) { - dependsOn packageUberJar +tasks.register('createTar', Tar) { + dependsOn 'package' - // we want the file to be called cg.jar - from ('build/libs') - include originalUber - destinationDir file('build/libs/') - rename originalUber, "cg.jar" + archiveFileName = "cg.tar" + destinationDirectory = file('build/') + from (files('build/cg.jar')) +} - // this task actually does a copy, so this part removes the original - doLast { - delete('build/libs/' + originalUber) - } +tasks.register('dist') { + dependsOn createZip + dependsOn createTar } diff --git a/pcgroups/README.md b/pcgroups/README.md index 331021d..e59ff56 100644 --- a/pcgroups/README.md +++ b/pcgroups/README.md @@ -2,9 +2,17 @@ # Partitioned Consumer Groups +![Artifact](https://img.shields.io/badge/Artifact-io.synadia:pcgroups-197556?labelColor=grey&style=flat) +![0.1.0](https://img.shields.io/badge/Current_Release-0.1.0-27AAE0) +![0.1.1](https://img.shields.io/badge/Current_Snapshot-0.1.1--SNAPSHOT-27AAE0) +[![Dependencies Help](https://img.shields.io/badge/Dependencies%20Help-27AAE0)](https://github.com/synadia-io/orbit.java?tab=readme-ov-file#dependencies) +[![javadoc](https://javadoc.io/badge2/io.synadia/pcgroups/javadoc.svg)](https://javadoc.io/doc/io.synadia/pcgroups) +[![Maven Central](https://img.shields.io/maven-central/v/io.synadia/pcgroups)](https://img.shields.io/maven-central/v/io.synadia/pcgroups) + Initial implementation of a client-side partitioned consumer group feature for NATS streams leveraging some of the new features introduced in `nats-server` version 2.11. Note that post 2.11 versions of `nats-server` may include new features related to the consumer group use case that could render this client-side library unneeded (or make much smaller) + # Overview This library enables the parallelization through partitioning of the consumption of messages from a stream while ensuring a strict order of not just delivery but also successful consumption of the messages using all or parts of the message's subject as a partitioning key. @@ -54,6 +62,9 @@ Included is a small command line interface tool, named `cg` and located in the ` This `cg` CLI tool can be used by passing it commands and arguments directly, or with an interactive prompt using the `prompt` command (e.g. `cg static prompt`). +For more details on the CLI visit the [Partitioned Consumer Groups CLI Project](https://github.com/synadia-io/orbit.java/tree/main/pcgroups-cli) + + ## Demo walkthrough ### Static diff --git a/pcgroups/build.gradle b/pcgroups/build.gradle index 75f3332..225e274 100644 --- a/pcgroups/build.gradle +++ b/pcgroups/build.gradle @@ -11,7 +11,7 @@ plugins { id("signing") } -def jarVersion = "0.1.0" +def jarVersion = "0.1.1" group = 'io.synadia' def isRelease = System.getenv("BUILD_EVENT") == "release"