Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 0 additions & 46 deletions .github/workflows/pcgcli-main.yml

This file was deleted.

28 changes: 21 additions & 7 deletions .github/workflows/pcgcli-pr.yml → .github/workflows/pcgcli.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -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."
Expand Down
82 changes: 82 additions & 0 deletions pcgroups-cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<img src="../orbit_shorter.png" alt="Orbit">

# Partitioned Consumer Groups CLI

The Partitioned Consumer Groups CLI is a command line tool. In the usage,

`cg` stands for `java -jar <path>/cg.jar`

```
Usage: cg <command> [options]

Commands:
static Static consumer groups mode
elastic Elastic consumer groups mode

Use 'cg <command> --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.
62 changes: 29 additions & 33 deletions pcgroups-cli/build.gradle
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -27,44 +20,47 @@ 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'
testImplementation 'org.junit.jupiter:junit-jupiter:5.14.1'
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
}
11 changes: 11 additions & 0 deletions pcgroups/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion pcgroups/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down